diff --git a/src/ConnectionPool.cpp b/src/ConnectionPool.cpp index df16ef820..1b87e15ea 100644 --- a/src/ConnectionPool.cpp +++ b/src/ConnectionPool.cpp @@ -8,6 +8,8 @@ #include "Application.h" #include "utils.h" +// XXX On Windows make sure OpenSSL PRNG is seeded: EGADS + ConnectionPool::ConnectionPool() : iConnecting(0), mCtx(boost::asio::ssl::context::sslv23) @@ -17,16 +19,16 @@ ConnectionPool::ConnectionPool() : | 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"); + 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) @@ -138,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()) { @@ -164,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 5d76d5a04..521090d94 100644 --- a/src/ConnectionPool.h +++ b/src/ConnectionPool.h @@ -54,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 9c67d98f9..c248dd41b 100644 --- a/src/Peer.cpp +++ b/src/Peer.cpp @@ -25,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(); @@ -55,7 +55,7 @@ void Peer::detach() // mSocketSsl.close(); if (!mIpPort.first.empty()) { - theApp->getConnectionPool().peerDisconnected(shared_from_this()); + theApp->getConnectionPool().peerDisconnected(shared_from_this(), mIpPort, mNodePublic); mIpPort.first.clear(); } } @@ -66,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), @@ -96,11 +96,15 @@ void Peer::connect(const std::string strIp, int iPort) } } +// 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 << "Peer::handleStart: failed:" << error << std::endl; + std::cerr << "Peer::handleStart: failed:" << error << std::endl; detach(); } else @@ -115,19 +119,16 @@ void Peer::handleConnect(const boost::system::error_code& error, boost::asio::ip { if (error) { - std::cout << "Socket Connect failed:" << error << std::endl; + std::cerr << "Socket Connect failed:" << error << std::endl; detach(); } else { - std::cout << "Socket Connected." << std::endl; + 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); - // XXX Do what? - // mSocketSsl.set_verify_callback(boost::asio::ssl::rfc2818_verification(mDeqSites[0]), mShutdown); - mSocketSsl.async_handshake(boost::asio::ssl::stream::client, boost::bind(&Peer::handleStart, shared_from_this(), @@ -145,24 +146,24 @@ void Peer::connected(const boost::system::error_code& error) 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); @@ -170,9 +171,6 @@ void Peer::connected(const boost::system::error_code& error) 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::server, boost::bind(&Peer::handleStart, shared_from_this(), @@ -242,7 +240,7 @@ void Peer::handle_read_header(const boost::system::error_code& error) else { detach(); - std::cout << "Peer::handle_read_header: 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; } } @@ -256,7 +254,7 @@ void Peer::handle_read_body(const boost::system::error_code& error) else { detach(); - std::cout << "Peer::handle_read_body: 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; } } @@ -283,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; @@ -292,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; @@ -301,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; @@ -310,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; @@ -319,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; @@ -328,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; @@ -337,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; @@ -346,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; @@ -355,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; @@ -364,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; @@ -373,7 +371,7 @@ 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; @@ -383,7 +381,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; @@ -392,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; @@ -401,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; @@ -410,7 +408,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; #endif @@ -419,7 +417,7 @@ void Peer::processReadBuffer() 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; @@ -428,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; } } } @@ -447,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; @@ -470,7 +468,7 @@ void Peer::recvHello(newcoin::TMHello& packet) if (bDetach) { - mPublicKey.clear(); + mNodePublic.clear(); detach(); } } @@ -700,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; } @@ -825,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 d1bee4a2c..7e943e286 100644 --- a/src/Peer.h +++ b/src/Peer.h @@ -28,7 +28,7 @@ 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); diff --git a/src/PeerDoor.cpp b/src/PeerDoor.cpp index e417ab012..13dc15e5b 100644 --- a/src/PeerDoor.cpp +++ b/src/PeerDoor.cpp @@ -14,23 +14,35 @@ using namespace std; using namespace boost::asio::ip; // Generate DH for SSL connection. -static DH* handleTmpDh(SSL* ssl, int is_export, int keylength) +static DH* handleTmpDh(SSL* ssl, int is_export, int iKeyLength) { - // We don't care if for export or what length was requested. Always do 512. - static DH* mDh512 = 0; + // We don't care if for export. + static DH* sdh512 = 0; + static DH* sdh1024 = 0; - if (!mDh512) + if (!sdh512 && 512 == iKeyLength) { int iCodes; do { - mDh512 = DH_generate_parameters(512, DH_GENERATOR_5, NULL, NULL); + sdh512 = DH_generate_parameters(512, DH_GENERATOR_5, NULL, NULL); iCodes = 0; - DH_check(mDh512, &iCodes); + 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)); } - return mDh512; + 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) : @@ -43,7 +55,8 @@ PeerDoor::PeerDoor(boost::asio::io_service& io_service) : | 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"); + 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;