From 4ebc2f8320c1f8f045b384712a771a7bc51bb4c6 Mon Sep 17 00:00:00 2001 From: subtly Date: Wed, 18 Feb 2015 00:56:52 -0500 Subject: [PATCH] reenable sessions. more refactor. --- libp2p/Host.cpp | 23 ++++---- libp2p/Host.h | 153 ++++++++++++++++++++++++------------------------ 2 files changed, 86 insertions(+), 90 deletions(-) diff --git a/libp2p/Host.cpp b/libp2p/Host.cpp index 1b6d8d65b..d79b6bd39 100644 --- a/libp2p/Host.cpp +++ b/libp2p/Host.cpp @@ -338,7 +338,7 @@ void Host::runAcceptor() { // doHandshake takes ownersihp of *s via std::move // incoming connection; we don't yet know nodeid - auto handshake = make_shared(m_alias, s); + auto handshake = make_shared(this, s); handshake->start(); success = true; } @@ -399,10 +399,10 @@ void PeerHandshake::transition(boost::system::error_code _ech) { bytesConstRef nonce(&auth[Signature::size + h256::size + Public::size], h256::size); // E(remote-pubk, S(ecdhe-random, ecdh-shared-secret^nonce) || H(ecdhe-random-pubk) || pubk || nonce || 0x0) - crypto::ecdh::agree(alias.sec(), remote, ss); + crypto::ecdh::agree(host->m_alias.sec(), remote, ss); sign(ecdhe.seckey(), ss ^ this->nonce).ref().copyTo(sig); sha3(ecdhe.pubkey().ref(), hepubk); - alias.pub().ref().copyTo(pubk); + host->m_alias.pub().ref().copyTo(pubk); this->nonce.ref().copyTo(nonce); auth[auth.size() - 1] = 0x0; encrypt(remote, &auth, authCipher); @@ -423,7 +423,7 @@ void PeerHandshake::transition(boost::system::error_code _ech) { transition(ec); else { - decrypt(alias.sec(), bytesConstRef(&authCipher), auth); + decrypt(host->m_alias.sec(), bytesConstRef(&authCipher), auth); bytesConstRef sig(&auth[0], Signature::size); bytesConstRef hepubk(&auth[Signature::size], h256::size); bytesConstRef pubk(&auth[Signature::size + h256::size], Public::size); @@ -431,7 +431,7 @@ void PeerHandshake::transition(boost::system::error_code _ech) { pubk.copyTo(remote.ref()); nonce.copyTo(remoteNonce.ref()); - crypto::ecdh::agree(alias.sec(), remote, ss); + crypto::ecdh::agree(host->m_alias.sec(), remote, ss); remoteEphemeral = recover(*(Signature*)sig.data(), ss ^ remoteNonce); assert(sha3(remoteEphemeral) == *(h256*)hepubk.data()); transition(); @@ -451,7 +451,7 @@ void PeerHandshake::transition(boost::system::error_code _ech) { transition(ec); else { - decrypt(alias.sec(), bytesConstRef(&ackCipher), ack); + decrypt(host->m_alias.sec(), bytesConstRef(&ackCipher), ack); bytesConstRef(&ack).cropped(0, Public::size).copyTo(remoteEphemeral.ref()); bytesConstRef(&ack).cropped(Public::size, h256::size).copyTo(remoteNonce.ref()); transition(); @@ -551,7 +551,7 @@ void PeerHandshake::transition(boost::system::error_code _ech) { { shared_ptr p; // todo: need host -// p = m_peers[remote]; + p = host->m_peers[remote]; if (!p) { @@ -562,10 +562,9 @@ void PeerHandshake::transition(boost::system::error_code _ech) { p->m_lastDisconnect = NoDisconnect; p->m_lastConnected = std::chrono::system_clock::now(); p->m_failedAttempts = 0; - - // todo: need host -// auto ps = std::make_shared(this, move(*socket), p); -// ps->start(); + + auto ps = std::make_shared(host, move(*socket), p); + ps->start(); } // todo: PeerSession needs to take ownership of k (PeerSecrets) @@ -877,7 +876,7 @@ void Host::connect(std::shared_ptr const& _p) else { clog(NetConnect) << "Connected to" << _p->id.abridged() << "@" << _p->peerEndpoint(); - auto handshake = make_shared(m_alias, s, _p->id); + auto handshake = make_shared(this, s, _p->id); handshake->start(); } Guard l(x_pendingNodeConns); diff --git a/libp2p/Host.h b/libp2p/Host.h index 31ca22442..9a49d2706 100644 --- a/libp2p/Host.h +++ b/libp2p/Host.h @@ -63,98 +63,21 @@ private: Host& m_host; }; - -/** - * @brief Key material and derived secrets for TCP peer connection. - */ -struct PeerSecrets -{ - friend class PeerHandshake; -protected: - Secret encryptK; - Secret macK; - h256 egressMac; - h256 ingressMac; - - bytes magicCipherAndMac; - bytes recvdMagicCipherAndMac; -}; - -struct PeerHandshake: public std::enable_shared_from_this -{ - friend class Host; - enum State - { - New, // New->AckAuth [egress: tx auth, ingress: rx auth] - AckAuth, // AckAuth->Authenticating [egress: rx ack, ingress: tx ack] - Authenticating, // Authenticating [tx caps, rx caps, authenticate] - }; - - /// Handshake for ingress connection. Takes ownership of socket. - PeerHandshake(KeyPair const& _alias, bi::tcp::socket* _socket): alias(_alias), socket(std::move(_socket)), originated(false) { crypto::Nonce::get().ref().copyTo(nonce.ref()); } - - /// Handshake for egress connection to _remote. Takes ownership of socket. - PeerHandshake(KeyPair const& _alias, bi::tcp::socket* _socket, NodeId _remote): alias(_alias), socket(std::move(_socket)), originated(true), remote(_remote) { crypto::Nonce::get().ref().copyTo(nonce.ref()); } - - ~PeerHandshake() { delete socket; } - -protected: - /// Returns true when the auth message is to be sent or received. - bool isNew() { return state == New; } - - /// Returns true when the ack message is to be sent or received. - bool isAcking() { return state == AckAuth; } - - /// Returns true when auth and ack messages have been received and caps message is to be sent, received, and authenticated. - bool isAuthenticating() { return state == Authenticating; } - - void start() { transition(); } - -private: - void transition(boost::system::error_code _ech = boost::system::error_code()); - - /// Current state of handshake. - State state = New; - - KeyPair const& alias; - - /// Node id of remote host for socket. - NodeId remote; - - bi::tcp::socket* socket; - bool originated = false; - - bytes auth; - bytes authCipher; - bytes ack; - bytes ackCipher; - Secret ss; - Secret ess; - - crypto::ECDHE ecdhe; - h256 nonce; - - Public remoteEphemeral; - h256 remoteNonce; -}; /** * @brief The Host class * Capabilities should be registered prior to startNetwork, since m_capabilities is not thread-safe. * - * @todo exceptions when nodeTable not set (prior to start) - * @todo onNodeTableEvent: move peer-connection logic into ensurePeers * @todo handshake: gracefully disconnect peer if peer already connected * @todo abstract socket -> IPConnection * @todo determinePublic: ipv6, udp * @todo handle conflict if addNode/requireNode called and Node already exists w/conflicting tcp or udp port - * @todo write host identifier to disk w/nodes * @todo per-session keepalive/ping instead of broadcast; set ping-timeout via median-latency - * @todo configuration-management (NetworkPrefs+Keys+Topology) */ class Host: public Worker { friend class HostNodeTableHandler; + friend struct PeerHandshake; friend class Session; friend class HostCapabilityFace; @@ -308,5 +231,79 @@ private: bool m_accepting = false; }; +/** + * @brief Key material and derived secrets for TCP peer connection. + */ +struct PeerSecrets +{ + friend struct PeerHandshake; +protected: + Secret encryptK; + Secret macK; + h256 egressMac; + h256 ingressMac; + + bytes magicCipherAndMac; + bytes recvdMagicCipherAndMac; +}; + +struct PeerHandshake: public std::enable_shared_from_this +{ + friend class Host; + enum State + { + New, // New->AckAuth [egress: tx auth, ingress: rx auth] + AckAuth, // AckAuth->Authenticating [egress: rx ack, ingress: tx ack] + Authenticating, // Authenticating [tx caps, rx caps, authenticate] + }; + + /// Handshake for ingress connection. Takes ownership of socket. + PeerHandshake(Host* _host, bi::tcp::socket* _socket): host(_host), socket(std::move(_socket)), originated(false) { crypto::Nonce::get().ref().copyTo(nonce.ref()); } + + /// Handshake for egress connection to _remote. Takes ownership of socket. + PeerHandshake(Host* _host, bi::tcp::socket* _socket, NodeId _remote): host(_host), socket(std::move(_socket)), originated(true), remote(_remote) { crypto::Nonce::get().ref().copyTo(nonce.ref()); } + + ~PeerHandshake() { delete socket; } + +protected: + /// Returns true when the auth message is to be sent or received. + bool isNew() { return state == New; } + + /// Returns true when the ack message is to be sent or received. + bool isAcking() { return state == AckAuth; } + + /// Returns true when auth and ack messages have been received and caps message is to be sent, received, and authenticated. + bool isAuthenticating() { return state == Authenticating; } + + void start() { transition(); } + +private: + void transition(boost::system::error_code _ech = boost::system::error_code()); + + /// Current state of handshake. + State state = New; + + Host* host; + + /// Node id of remote host for socket. + NodeId remote; + + bi::tcp::socket* socket; + bool originated = false; + + bytes auth; + bytes authCipher; + bytes ack; + bytes ackCipher; + Secret ss; + Secret ess; + + crypto::ECDHE ecdhe; + h256 nonce; + + Public remoteEphemeral; + h256 remoteNonce; +}; + } }