diff --git a/src/Application.cpp b/src/Application.cpp index ccd2ca404..7c097cb26 100644 --- a/src/Application.cpp +++ b/src/Application.cpp @@ -11,6 +11,7 @@ #include "RPCDoor.h" #include "BitcoinUtil.h" #include "key.h" +#include "utils.h" Application* theApp=NULL; @@ -45,7 +46,7 @@ Application::Application() : mTxnDB(NULL), mLedgerDB(NULL), mWalletDB(NULL), mHashNodeDB(NULL), mNetNodeDB(NULL), mPeerDoor(NULL), mRPCDoor(NULL) { - theConfig.load(); + nothing(); } extern const char *TxnDBInit[], *LedgerDBInit[], *WalletDBInit[], *HashNodeDBInit[], *NetNodeDBInit[]; diff --git a/src/Config.cpp b/src/Config.cpp index f8066f915..62baef258 100644 --- a/src/Config.cpp +++ b/src/Config.cpp @@ -6,35 +6,38 @@ #include #include -#define CONFIG_FILE_NAME SYSTEM_NAME "d.cfg" // newcoind.cfg -#define SECTION_PEER_IP "peer_ip" -#define SECTION_PEER_PORT "peer_port" -#define SECTION_RPC_IP "rpc_ip" -#define SECTION_RPC_PORT "rpc_port" -#define SECTION_VALIDATION_PASSWORD "validation_password" -#define SECTION_VALIDATION_KEY "validation_key" +#define CONFIG_FILE_NAME SYSTEM_NAME "d.cfg" // newcoind.cfg +#define SECTION_PEER_IP "peer_ip" +#define SECTION_PEER_PORT "peer_port" +#define SECTION_RPC_IP "rpc_ip" +#define SECTION_RPC_PORT "rpc_port" +#define SECTION_VALIDATION_PASSWORD "validation_password" +#define SECTION_VALIDATION_KEY "validation_key" +#define SECTION_PEER_SSL_CIPHER_LIST "peer_ssl_cipher_list" Config theConfig; Config::Config() { - VERSION=1; + VERSION = 1; - NETWORK_START_TIME=1319844908; + NETWORK_START_TIME = 1319844908; - PEER_PORT=SYSTEM_PEER_PORT; - RPC_PORT=5001; - NUMBER_CONNECTIONS=30; + PEER_PORT = SYSTEM_PEER_PORT; + RPC_PORT = 5001; + NUMBER_CONNECTIONS = 30; // a new ledger every 30 min - LEDGER_SECONDS=(60*30); + LEDGER_SECONDS = (60*30); - RPC_USER="admin"; - RPC_PASSWORD="pass"; + RPC_USER = "admin"; + RPC_PASSWORD = "pass"; - DATA_DIR="db/"; + DATA_DIR = "db/"; - TRANSACTION_FEE_BASE=1000; + PEER_SSL_CIPHER_LIST = DEFAULT_PEER_SSL_CIPHER_LIST; + + TRANSACTION_FEE_BASE = 1000; } void Config::load() @@ -73,6 +76,8 @@ void Config::load() (void) sectionSingleB(secConfig, SECTION_VALIDATION_PASSWORD, VALIDATION_PASSWORD); (void) sectionSingleB(secConfig, SECTION_VALIDATION_KEY, VALIDATION_KEY); + + (void) sectionSingleB(secConfig, SECTION_PEER_SSL_CIPHER_LIST, PEER_SSL_CIPHER_LIST); } } diff --git a/src/Config.h b/src/Config.h index 951c5817e..9974d4d94 100644 --- a/src/Config.h +++ b/src/Config.h @@ -7,6 +7,9 @@ const int SYSTEM_PEER_PORT=6561; +// Allow anonymous DH. +#define DEFAULT_PEER_SSL_CIPHER_LIST "ALL:!LOW:!EXP:!MD5:@STRENGTH" + class Config { public: @@ -42,6 +45,8 @@ public: std::string VALIDATION_PASSWORD; std::string VALIDATION_KEY; + std::string PEER_SSL_CIPHER_LIST; + // configuration parameters std::string DATA_DIR; diff --git a/src/ConnectionPool.cpp b/src/ConnectionPool.cpp index 685ad2f41..1b87e15ea 100644 --- a/src/ConnectionPool.cpp +++ b/src/ConnectionPool.cpp @@ -8,18 +8,27 @@ #include "Application.h" #include "utils.h" +// XXX On Windows make sure OpenSSL PRNG is seeded: EGADS 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); + if (1 != SSL_CTX_set_cipher_list(mCtx.native_handle(), theConfig.PEER_SSL_CIPHER_LIST.c_str())) + std::runtime_error("Error setting cipher list (no valid ciphers)."); +} void ConnectionPool::start() { // XXX Start running policy. } -// XXX Broken don't send a message to a peer if we got it from the peer. +// XXX Broken: also don't send a message to a peer if we got it from the peer. void ConnectionPool::relayMessage(Peer* fromPeer, PackedMessage::pointer msg) { BOOST_FOREACH(naPeer pair, mConnectedMap) @@ -80,7 +89,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; @@ -131,18 +140,17 @@ bool ConnectionPool::peerConnected(Peer::pointer peer, const NewcoinAddress& na) return bSuccess; } -void ConnectionPool::peerDisconnected(Peer::pointer peer) +void ConnectionPool::peerDisconnected(Peer::pointer peer, const ipPort& ipPeer, const NewcoinAddress& naPeer) { std::cerr << "ConnectionPool::peerDisconnected: " << peer->mIpPort.first << " " << peer->mIpPort.second << std::endl; boost::mutex::scoped_lock sl(mPeerLock); - // XXX Don't access member variable directly. - if (peer->mPublicKey.isValid()) + if (naPeer.isValid()) { boost::unordered_map::iterator itCm; - itCm = mConnectedMap.find(peer->mPublicKey); + itCm = mConnectedMap.find(naPeer); if (itCm == mConnectedMap.end()) { @@ -157,16 +165,15 @@ void ConnectionPool::peerDisconnected(Peer::pointer peer) } } - // XXX Don't access member variable directly. boost::unordered_map::iterator itIp; - itIp = mIpMap.find(peer->mIpPort); + itIp = mIpMap.find(ipPeer); if (itIp == mIpMap.end()) { // Did not find it. Not already connecting or connected. std::cerr << "Internal Error: peer wasn't connected: " - << peer->mIpPort.first << " " << peer->mIpPort.second << std::endl; + << ipPeer.first << " " << ipPeer.second << std::endl; // XXX Bad error. } else diff --git a/src/ConnectionPool.h b/src/ConnectionPool.h index 135ab3b25..521090d94 100644 --- a/src/ConnectionPool.h +++ b/src/ConnectionPool.h @@ -1,6 +1,7 @@ #ifndef __CONNECTION_POOL__ #define __CONNECTION_POOL__ +#include #include #include "Peer.h" @@ -27,6 +28,8 @@ private: // Non-thin peers which we are connected to. boost::unordered_map mConnectedMap; + boost::asio::ssl::context mCtx; + public: ConnectionPool(); @@ -51,7 +54,7 @@ public: bool peerConnected(Peer::pointer peer, const NewcoinAddress& na); // No longer connected. - void peerDisconnected(Peer::pointer peer); + void peerDisconnected(Peer::pointer peer, const ipPort& ipPeer, const NewcoinAddress& naPeer); Json::Value getPeersJson(); diff --git a/src/Peer.cpp b/src/Peer.cpp index 4192d070b..c248dd41b 100644 --- a/src/Peer.cpp +++ b/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) { } @@ -27,9 +25,9 @@ void Peer::handle_write(const boost::system::error_code& error, size_t bytes_tra { #ifdef DEBUG if(error) - std::cout << "Peer::handle_write Error: " << error << " bytes: " << bytes_transferred << std::endl; + std::cerr << "Peer::handle_write Error: " << error << " bytes: " << bytes_transferred << std::endl; else - std::cout << "Peer::handle_write bytes: "<< bytes_transferred << std::endl; + std::cerr << "Peer::handle_write bytes: "<< bytes_transferred << std::endl; #endif mSendingPacket=PackedMessage::pointer(); @@ -54,10 +52,10 @@ 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()); + theApp->getConnectionPool().peerDisconnected(shared_from_this(), mIpPort, mNodePublic); mIpPort.first.clear(); } } @@ -68,7 +66,7 @@ void Peer::connect(const std::string strIp, int iPort) { int iPortAct = iPort < 0 ? SYSTEM_PEER_PORT : iPort; - std::cout << "Peer::connect: " << strIp << " " << iPort << std::endl; + std::cerr << "Peer::connect: " << strIp << " " << iPort << std::endl; mIpPort = make_pair(strIp, iPort); boost::asio::ip::tcp::resolver::query query(strIp, boost::lexical_cast(iPortAct), @@ -86,87 +84,104 @@ 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::handleConnect(const boost::system::error_code& error, boost::asio::ip::tcp::resolver::iterator it) +// We have an ecrypted connection to the peer. +// Have it say who it is so we know to avoid redundant connections. +// Establish that it really who we are talking to by having it sign a connection detail. +// XXX Also need to establish no man in the middle attack is in progress. +void Peer::handleStart(const boost::system::error_code& error) { if (error) { - std::cout << "Socket Connect failed:" << error << std::endl; + std::cerr << "Peer::handleStart: failed:" << error << std::endl; detach(); } else { - std::cout << "Socket Connected." << std::endl; - start_read_header(); sendHello(); } } -// Peer connected via door. +// Connect as client. +void Peer::handleConnect(const boost::system::error_code& error, boost::asio::ip::tcp::resolver::iterator it) +{ + if (error) + { + std::cerr << "Socket Connect failed:" << error << std::endl; + detach(); + } + else + { + std::cerr << "Socket Connected." << std::endl; + + mSocketSsl.lowest_layer().set_option(boost::asio::ip::tcp::no_delay(true)); + mSocketSsl.set_verify_mode(boost::asio::ssl::verify_none); + + mSocketSsl.async_handshake(boost::asio::ssl::stream::client, + boost::bind(&Peer::handleStart, + shared_from_this(), + boost::asio::placeholders::error)); + } +} + +// 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(); if (iPort == SYSTEM_PEER_PORT) iPort = -1; - std::cout << "Remote peer: accept: " << strIp << " " << iPort << std::endl; + std::cerr << "Remote peer: accept: " << strIp << " " << iPort << std::endl; if (error) { - std::cout << "Remote peer: accept error: " << error << std::endl; + std::cerr << "Remote peer: accept error: " << error << std::endl; detach(); } else if (!theApp->getConnectionPool().peerRegister(shared_from_this(), strIp, iPort)) { - std::cout << "Remote peer: rejecting." << std::endl; + std::cerr << "Remote peer: rejecting." << std::endl; // XXX Reject with a rejection message: already connected detach(); } else { - // Not redundant, add to connection list. + // Not redundant ip and port, add to connection list. - std::cout << "Remote peer: accepted." << std::endl; + std::cerr << "Remote peer: accepted." << std::endl; //BOOST_LOG_TRIVIAL(info) << "Connected to Peer."; 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); + + mSocketSsl.async_handshake(boost::asio::ssl::stream::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 +209,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 +220,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 +240,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::cerr << "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 +254,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::cerr << "Peer::handle_read_body: Error: " << error << std::endl; //else BOOST_LOG_TRIVIAL(info) << "Error: " << error; } } @@ -266,7 +281,7 @@ void Peer::processReadBuffer() newcoin::TMHello msg; if(msg.ParseFromArray(&mReadbuf[HEADER_SIZE], mReadbuf.size() - HEADER_SIZE)) recvHello(msg); - else std::cout << "parse error: " << type << std::endl; //else BOOST_LOG_TRIVIAL(info) << "Error: " << error; + else std::cerr << "parse error: " << type << std::endl; //else BOOST_LOG_TRIVIAL(info) << "Error: " << error; } break; @@ -275,7 +290,7 @@ void Peer::processReadBuffer() newcoin::TMErrorMsg msg; if(msg.ParseFromArray(&mReadbuf[HEADER_SIZE], mReadbuf.size() - HEADER_SIZE)) recvErrorMessage(msg); - else std::cout << "pars error: " << type << std::endl; + else std::cerr << "parse error: " << type << std::endl; } break; @@ -284,7 +299,7 @@ void Peer::processReadBuffer() newcoin::TMPing msg; if(msg.ParseFromArray(&mReadbuf[HEADER_SIZE], mReadbuf.size() - HEADER_SIZE)) recvPing(msg); - else std::cout << "pars error: " << type << std::endl; + else std::cerr << "parse error: " << type << std::endl; } break; @@ -293,7 +308,7 @@ void Peer::processReadBuffer() newcoin::TMGetContacts msg; if(msg.ParseFromArray(&mReadbuf[HEADER_SIZE], mReadbuf.size() - HEADER_SIZE)) recvGetContacts(msg); - else std::cout << "pars error: " << type << std::endl; + else std::cerr << "parse error: " << type << std::endl; } break; @@ -302,7 +317,7 @@ void Peer::processReadBuffer() newcoin::TMContact msg; if(msg.ParseFromArray(&mReadbuf[HEADER_SIZE], mReadbuf.size() - HEADER_SIZE)) recvContact(msg); - else std::cout << "pars error: " << type << std::endl; + else std::cerr << "parse error: " << type << std::endl; } break; @@ -311,7 +326,7 @@ void Peer::processReadBuffer() newcoin::TMSearchTransaction msg; if(msg.ParseFromArray(&mReadbuf[HEADER_SIZE], mReadbuf.size() - HEADER_SIZE)) recvSearchTransaction(msg); - else std::cout << "pars error: " << type << std::endl; + else std::cerr << "parse error: " << type << std::endl; } break; @@ -320,7 +335,7 @@ void Peer::processReadBuffer() newcoin::TMGetAccount msg; if(msg.ParseFromArray(&mReadbuf[HEADER_SIZE], mReadbuf.size() - HEADER_SIZE)) recvGetAccount(msg); - else std::cout << "pars error: " << type << std::endl; + else std::cerr << "parse error: " << type << std::endl; } break; @@ -329,7 +344,7 @@ void Peer::processReadBuffer() newcoin::TMAccount msg; if(msg.ParseFromArray(&mReadbuf[HEADER_SIZE], mReadbuf.size() - HEADER_SIZE)) recvAccount(msg); - else std::cout << "pars error: " << type << std::endl; + else std::cerr << "parse error: " << type << std::endl; } break; @@ -338,7 +353,7 @@ void Peer::processReadBuffer() newcoin::TMTransaction msg; if(msg.ParseFromArray(&mReadbuf[HEADER_SIZE], mReadbuf.size() - HEADER_SIZE)) recvTransaction(msg); - else std::cout << "pars error: " << type << std::endl; + else std::cerr << "parse error: " << type << std::endl; } break; @@ -347,7 +362,7 @@ void Peer::processReadBuffer() newcoin::TMGetLedger msg; if(msg.ParseFromArray(&mReadbuf[HEADER_SIZE], mReadbuf.size() - HEADER_SIZE)) recvGetLedger(msg); - else std::cout << "pars error: " << type << std::endl; + else std::cerr << "parse error: " << type << std::endl; } break; @@ -356,17 +371,17 @@ void Peer::processReadBuffer() newcoin::TMLedgerData msg; if(msg.ParseFromArray(&mReadbuf[HEADER_SIZE], mReadbuf.size() - HEADER_SIZE)) recvLedger(msg); - else std::cout << "pars error: " << type << std::endl; + else std::cerr << "parse error: " << type << std::endl; } break; - #if 0 +#if 0 case newcoin::mtPROPOSE_LEDGER: { newcoin::TM msg; if(msg.ParseFromArray(&mReadbuf[HEADER_SIZE], mReadbuf.size() - HEADER_SIZE)) recv(msg); - else std::cout << "pars error: " << type << std::endl; + else std::cerr << "parse error: " << type << std::endl; } break; @@ -375,7 +390,7 @@ void Peer::processReadBuffer() newcoin::TM msg; if(msg.ParseFromArray(&mReadbuf[HEADER_SIZE], mReadbuf.size() - HEADER_SIZE)) recv(msg); - else std::cout << "pars error: " << type << std::endl; + else std::cerr << "parse error: " << type << std::endl; } break; @@ -384,7 +399,7 @@ void Peer::processReadBuffer() newcoin::TM msg; if(msg.ParseFromArray(&mReadbuf[HEADER_SIZE], mReadbuf.size() - HEADER_SIZE)) recv(msg); - else std::cout << "pars error: " << type << std::endl; + else std::cerr << "parse error: " << type << std::endl; } break; @@ -393,18 +408,16 @@ void Peer::processReadBuffer() newcoin::TM msg; if(msg.ParseFromArray(&mReadbuf[HEADER_SIZE], mReadbuf.size() - HEADER_SIZE)) recv(msg); - else std::cout << "pars error: " << type << std::endl; + else std::cerr << "parse error: " << type << std::endl; } break; - - #endif - +#endif case newcoin::mtGET_OBJECT: { newcoin::TMGetObjectByHash msg; if(msg.ParseFromArray(&mReadbuf[HEADER_SIZE], mReadbuf.size() - HEADER_SIZE)) recvGetObjectByHash(msg); - else std::cout << "pars error: " << type << std::endl; + else std::cerr << "parse error: " << type << std::endl; } break; @@ -413,12 +426,12 @@ void Peer::processReadBuffer() newcoin::TMObjectByHash msg; if(msg.ParseFromArray(&mReadbuf[HEADER_SIZE], mReadbuf.size() - HEADER_SIZE)) recvObjectByHash(msg); - else std::cout << "pars error: " << type << std::endl; + else std::cerr << "parse error: " << type << std::endl; } break; default: - std::cout << "Unknown Msg: " << type << std::endl; //else BOOST_LOG_TRIVIAL(info) << "Error: " << error; + std::cerr << "Unknown Msg: " << type << std::endl; //else BOOST_LOG_TRIVIAL(info) << "Error: " << error; } } } @@ -432,15 +445,15 @@ void Peer::recvHello(newcoin::TMHello& packet) #endif bool bDetach = true; - if (mPublicKey.isValid()) + if (mNodePublic.isValid()) { std::cerr << "Recv(Hello): Disconnect: Extraneous node public key." << std::endl; } - else if (!mPublicKey.setNodePublic(packet.nodepublic())) + else if (!mNodePublic.setNodePublic(packet.nodepublic())) { std::cerr << "Recv(Hello): Disconnect: Bad node public key." << std::endl; } - else if (!theApp->getConnectionPool().peerConnected(shared_from_this(), mPublicKey)) + else if (!theApp->getConnectionPool().peerConnected(shared_from_this(), mNodePublic)) { // Already connected, self, or some other reason. std::cerr << "Recv(Hello): Disconnect: Extraneous connection." << std::endl; @@ -455,7 +468,7 @@ void Peer::recvHello(newcoin::TMHello& packet) if (bDetach) { - mPublicKey.clear(); + mNodePublic.clear(); detach(); } } @@ -685,7 +698,7 @@ Json::Value Peer::getJson() { ret["ip"] = mIpPort.first; ret["port"] = mIpPort.second; - ret["public_key"] = mPublicKey.ToString(); + ret["public_key"] = mNodePublic.ToString(); return ret; } @@ -810,7 +823,7 @@ void Peer::receiveTransaction(TransactionPtr trans) } else { - std::cout << "Invalid transaction: " << trans->from() << std::endl; + std::cerr << "Invalid transaction: " << trans->from() << std::endl; } } diff --git a/src/Peer.h b/src/Peer.h index f86937688..7e943e286 100644 --- a/src/Peer.h +++ b/src/Peer.h @@ -28,18 +28,16 @@ public: static const int psbGotHello=0, psbSentHello=1, psbInMap=2, psbTrusted=3; static const int psbNoLedgers=4, psbNoTransactions=5, psbDownLevel=6; - NewcoinAddress mPublicKey; // Node public key of peer. + NewcoinAddress mNodePublic; // Node public key of peer. ipPort mIpPort; 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 mSocketSsl; + void handleStart(const boost::system::error_code& error); + protected: std::vector 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::lowest_layer_type& getSocket() { - return mSocket; + return mSocketSsl.lowest_layer(); } void connect(const std::string strIp, int iPort); diff --git a/src/PeerDoor.cpp b/src/PeerDoor.cpp index 5acf2a688..13dc15e5b 100644 --- a/src/PeerDoor.cpp +++ b/src/PeerDoor.cpp @@ -4,23 +4,68 @@ #include #include +#include //#include +#include #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 iKeyLength) { - cout << "Opening peer door on port: " << theConfig.PEER_PORT << endl; + // We don't care if for export. + static DH* sdh512 = 0; + static DH* sdh1024 = 0; + + if (!sdh512 && 512 == iKeyLength) + { + int iCodes; + + do { + sdh512 = DH_generate_parameters(512, DH_GENERATOR_5, NULL, NULL); + iCodes = 0; + DH_check(sdh512, &iCodes); + } while (iCodes & (DH_CHECK_P_NOT_PRIME|DH_CHECK_P_NOT_SAFE_PRIME|DH_UNABLE_TO_CHECK_GENERATOR|DH_NOT_SUITABLE_GENERATOR)); + } + + if (!sdh1024 && 512 != iKeyLength) + { + int iCodes; + + do { + sdh1024 = DH_generate_parameters(1024, DH_GENERATOR_5, NULL, NULL); + iCodes = 0; + DH_check(sdh1024, &iCodes); + } while (iCodes & (DH_CHECK_P_NOT_PRIME|DH_CHECK_P_NOT_SAFE_PRIME|DH_UNABLE_TO_CHECK_GENERATOR|DH_NOT_SUITABLE_GENERATOR)); + } + + return 512 == iKeyLength ? sdh512 : sdh1024; +} + +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); + if (1 != SSL_CTX_set_cipher_list(mCtx.native_handle(), theConfig.PEER_SSL_CIPHER_LIST.c_str())) + std::runtime_error("Error setting cipher list (no valid ciphers)."); + + 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, diff --git a/src/PeerDoor.h b/src/PeerDoor.h index a53defc6e..52b8fae1e 100644 --- a/src/PeerDoor.h +++ b/src/PeerDoor.h @@ -2,6 +2,7 @@ #include #include +#include #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); diff --git a/src/RPCDoor.cpp b/src/RPCDoor.cpp index 95a0aee15..2e85cad71 100644 --- a/src/RPCDoor.cpp +++ b/src/RPCDoor.cpp @@ -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 diff --git a/src/main.cpp b/src/main.cpp index dbb7c3e05..2d8721909 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -47,14 +47,17 @@ void printHelp() int parseCommandline(int argc, char* argv[]) { int ret=0; + + theConfig.load(); + if(argc>1) { - theConfig.load(); ret=commandLineRPC(argc, argv); if(ret) printHelp(); } else startApp(); + return ret; }