Remove RippleAddress:

The RippleAddress class was used to represent a number of fundamentally
different types: account public keys, account secret keys, node public
keys, node secret keys, seeds and generators.

The class is replaced by the following types:
* PublicKey for account and node public keys
* SecretKey for account and node private keys
* Generator for generating secp256k1 accounts
* Seed for account, node and generator seeds
This commit is contained in:
Nik Bougalis
2015-10-22 02:15:04 -07:00
parent e0af6ec567
commit 3974ddd8f7
116 changed files with 2445 additions and 4272 deletions

View File

@@ -26,7 +26,6 @@
#include <ripple/overlay/Cluster.h>
#include <ripple/overlay/ClusterNode.h>
#include <ripple/protocol/JsonFields.h>
#include <ripple/protocol/RippleAddress.h>
#include <ripple/protocol/tokens.h>
#include <boost/regex.hpp>
#include <memory.h>
@@ -39,7 +38,7 @@ Cluster::Cluster (beast::Journal j)
}
boost::optional<std::string>
Cluster::member (RippleAddress const& identity) const
Cluster::member (PublicKey const& identity) const
{
std::lock_guard<std::mutex> lock(mutex_);
@@ -53,12 +52,13 @@ std::size_t
Cluster::size() const
{
std::lock_guard<std::mutex> lock(mutex_);
return nodes_.size();
}
bool
Cluster::update (
RippleAddress const& identity,
PublicKey const& identity,
std::string name,
std::uint32_t loadFee,
NetClock::time_point reportTime)
@@ -120,23 +120,24 @@ Cluster::load (Section const& nodes)
return false;
}
auto const nid = RippleAddress::createNodePublic (match[1]);
auto const id = parseBase58<PublicKey>(
TokenType::TOKEN_NODE_PUBLIC, match[1]);
if (!nid.isValid())
if (!id)
{
JLOG (j_.error) <<
"Invalid node identity: " << match[1];
return false;
}
if (member (nid))
if (member (*id))
{
JLOG (j_.warning) <<
"Duplicate node identity: " << match[1];
continue;
}
update(nid, trim_whitespace(match[2]));
update(*id, trim_whitespace(match[2]));
}
return true;

View File

@@ -209,18 +209,16 @@ ConnectAttempt::onHandshake (error_code ec)
beast::IPAddressConversion::from_asio (local_endpoint)))
return fail("Duplicate connection");
bool success;
uint256 sharedValue;
std::tie(sharedValue, success) = makeSharedValue(
auto sharedValue = makeSharedValue(
stream_.native_handle(), journal_);
if (! success)
if (! sharedValue)
return close(); // makeSharedValue logs
beast::http::message req = makeRequest(
! overlay_.peerFinder().config().peerPrivate,
remote_endpoint_.address());
auto const hello = buildHello (
sharedValue,
*sharedValue,
overlay_.setup().public_ip,
beast::IPAddressConversion::from_asio(remote_endpoint_),
app_);
@@ -390,48 +388,48 @@ ConnectAttempt::processResponse (beast::http::message const& m,
return close();
}
bool success;
protocol::TMHello hello;
std::tie(hello, success) = parseHello (response_, journal_);
if(! success)
auto hello = parseHello (response_, journal_);
if(! hello)
return fail("processResponse: Bad TMHello");
uint256 sharedValue;
std::tie(sharedValue, success) = makeSharedValue(
auto sharedValue = makeSharedValue(
ssl_bundle_->stream.native_handle(), journal_);
if(! success)
if(! sharedValue)
return close(); // makeSharedValue logs
RippleAddress publicKey;
std::tie(publicKey, success) = verifyHello (hello,
sharedValue,
auto publicKey = verifyHello (*hello,
*sharedValue,
overlay_.setup().public_ip,
beast::IPAddressConversion::from_asio(remote_endpoint_),
journal_, app_);
if(! success)
if(! publicKey)
return close(); // verifyHello logs
if(journal_.info) journal_.info <<
"Public Key: " << publicKey.humanNodePublic();
"Public Key: " << toBase58 (
TokenType::TOKEN_NODE_PUBLIC,
*publicKey);
auto const protocol =
BuildInfo::make_protocol(hello.protoversion());
BuildInfo::make_protocol(hello->protoversion());
if(journal_.info) journal_.info <<
"Protocol: " << to_string(protocol);
auto member = app_.cluster().member(publicKey);
auto member = app_.cluster().member(*publicKey);
if (member)
{
if (journal_.info) journal_.info <<
"Cluster name: " << *member;
}
auto const result = overlay_.peerFinder().activate (slot_,
publicKey.toPublicKey(), static_cast<bool>(member));
*publicKey, static_cast<bool>(member));
if (result != PeerFinder::Result::success)
return fail("Outbound slots full");
auto const peer = std::make_shared<PeerImp>(app_,
std::move(ssl_bundle_), read_buf_.data(),
std::move(slot_), std::move(response_),
usage_, std::move(hello), publicKey, id_, overlay_);
usage_, *hello, *publicKey, id_, overlay_);
overlay_.add_active (peer);
}

View File

@@ -21,8 +21,9 @@
#include <ripple/basics/contract.h>
#include <ripple/app/misc/ValidatorList.h>
#include <ripple/core/DatabaseCon.h>
#include <ripple/crypto/Base58.h>
#include <ripple/overlay/impl/Manifest.h>
#include <ripple/protocol/RippleAddress.h>
#include <ripple/protocol/PublicKey.h>
#include <ripple/protocol/Sign.h>
#include <beast/http/rfc2616.h>
#include <stdexcept>

View File

@@ -232,31 +232,26 @@ OverlayImpl::onHandoff (std::unique_ptr <beast::asio::ssl_bundle>&& ssl_bundle,
}
handoff.moved = true;
bool success = true;
protocol::TMHello hello;
std::tie(hello, success) = parseHello (request, journal);
if(! success)
auto hello = parseHello (request, journal);
if(! hello)
return handoff;
uint256 sharedValue;
std::tie(sharedValue, success) = makeSharedValue(
auto sharedValue = makeSharedValue(
ssl_bundle->stream.native_handle(), journal);
if(! success)
if(! sharedValue)
return handoff;
RippleAddress publicKey;
std::tie(publicKey, success) = verifyHello (hello,
sharedValue,
auto publicKey = verifyHello (*hello,
*sharedValue,
setup_.public_ip,
beast::IPAddressConversion::from_asio(
remote_endpoint), journal, app_);
if(! success)
if(! publicKey)
return handoff;
auto const result = m_peerFinder->activate (slot,
publicKey.toPublicKey(),
static_cast<bool>(app_.cluster().member(publicKey)));
auto const result = m_peerFinder->activate (slot, *publicKey,
static_cast<bool>(app_.cluster().member(*publicKey)));
if (result != PeerFinder::Result::success)
{
m_peerFinder->on_closed(slot);
@@ -270,8 +265,8 @@ OverlayImpl::onHandoff (std::unique_ptr <beast::asio::ssl_bundle>&& ssl_bundle,
}
auto const peer = std::make_shared<PeerImp>(app_, id,
remote_endpoint, slot, std::move(request), hello, publicKey,
consumer, std::move(ssl_bundle), *this);
remote_endpoint, slot, std::move(request), *hello,
*publicKey, consumer, std::move(ssl_bundle), *this);
{
// As we are not on the strand, run() must be called
// while holding the lock, otherwise new I/O can be
@@ -403,8 +398,10 @@ OverlayImpl::add_active (std::shared_ptr<PeerImp> const& peer)
journal_.debug <<
"activated " << peer->getRemoteAddress() <<
" (" << peer->id() <<
":" << peer->getNodePublic().toPublicKey() << ")";
" (" << peer->id() << ":" <<
toBase58 (
TokenType::TOKEN_NODE_PUBLIC,
peer->getNodePublic()) << ")";
// As we are not on the strand, run() must be called
// while holding the lock, otherwise new I/O can be
@@ -652,7 +649,9 @@ OverlayImpl::activate (std::shared_ptr<PeerImp> const& peer)
journal_.debug <<
"activated " << peer->getRemoteAddress() <<
" (" << peer->id() <<
":" << peer->getNodePublic().toPublicKey() << ")";
":" << toBase58 (
TokenType::TOKEN_NODE_PUBLIC,
peer->getNodePublic()) << ")";
// We just accepted this peer so we have non-zero active peers
assert(size() != 0);
@@ -660,7 +659,7 @@ OverlayImpl::activate (std::shared_ptr<PeerImp> const& peer)
void
OverlayImpl::onPeerDeactivate (Peer::id_t id,
RippleAddress const& publicKey)
PublicKey const& publicKey)
{
std::lock_guard <decltype(mutex_)> lock (mutex_);
m_shortIdMap.erase(id);
@@ -804,8 +803,8 @@ OverlayImpl::crawl()
{
auto& pv = av.append(Json::Value(Json::objectValue));
pv[jss::public_key] = beast::base64_encode(
sp->getNodePublic().getNodePublic().data(),
sp->getNodePublic().getNodePublic().size());
sp->getNodePublic().data(),
sp->getNodePublic().size());
pv[jss::type] = sp->slot()->inbound() ?
"in" : "out";
pv[jss::uptime] =

View File

@@ -115,7 +115,7 @@ private:
TrafficCount m_traffic;
hash_map <PeerFinder::Slot::ptr,
std::weak_ptr <PeerImp>> m_peers;
hash_map<RippleAddress, std::weak_ptr<PeerImp>> m_publicKeyMap;
hash_map<PublicKey, std::weak_ptr<PeerImp>> m_publicKeyMap;
hash_map<Peer::id_t, std::weak_ptr<PeerImp>> m_shortIdMap;
Resolver& m_resolver;
std::atomic <Peer::id_t> next_id_;
@@ -226,7 +226,7 @@ public:
// Called when an active peer is destroyed.
void
onPeerDeactivate (Peer::id_t id, RippleAddress const& publicKey);
onPeerDeactivate (Peer::id_t id, PublicKey const& publicKey);
// UnaryFunc will be called as
// void(std::shared_ptr<PeerImp>&&)

View File

@@ -60,7 +60,7 @@ namespace ripple {
PeerImp::PeerImp (Application& app, id_t id, endpoint_type remote_endpoint,
PeerFinder::Slot::ptr const& slot, beast::http::message&& request,
protocol::TMHello const& hello, RippleAddress const& publicKey,
protocol::TMHello const& hello, PublicKey const& publicKey,
Resource::Consumer consumer,
std::unique_ptr<beast::asio::ssl_bundle>&& ssl_bundle,
OverlayImpl& overlay)
@@ -100,8 +100,7 @@ PeerImp::~PeerImp ()
name_ << " left cluster";
if (state_ == State::active)
{
assert(publicKey_.isSet());
assert(publicKey_.isValid());
assert(publicKey_.size() != 0);
overlay_.onPeerDeactivate(id_, publicKey_);
}
overlay_.peerFinder().on_closed (slot_);
@@ -262,7 +261,8 @@ PeerImp::json()
{
Json::Value ret (Json::objectValue);
ret[jss::public_key] = publicKey_.ToString ();
ret[jss::public_key] = toBase58 (
TokenType::TOKEN_NODE_PUBLIC, publicKey_);
ret[jss::address] = remote_address_.to_string();
if (m_inbound)
@@ -598,28 +598,27 @@ void PeerImp::doAccept()
if(journal_.debug) journal_.debug <<
"doAccept: " << remote_address_;
bool success;
uint256 sharedValue;
std::tie(sharedValue, success) = makeSharedValue(
auto sharedValue = makeSharedValue(
ssl_bundle_->stream.native_handle(), journal_);
// This shouldn't fail since we already computed
// the shared value successfully in OverlayImpl
if(! success)
if(! sharedValue)
return fail("makeSharedValue: Unexpected failure");
// TODO Apply headers to connection state.
auto resp = makeResponse(
! overlay_.peerFinder().config().peerPrivate,
http_message_, remote_address_, sharedValue);
http_message_, remote_address_, *sharedValue);
beast::http::write (write_buffer_, resp);
auto const protocol = BuildInfo::make_protocol(hello_.protoversion());
if(journal_.info) journal_.info <<
"Protocol: " << to_string(protocol);
if(journal_.info) journal_.info <<
"Public Key: " << publicKey_.humanNodePublic();
"Public Key: " << toBase58 (
TokenType::TOKEN_NODE_PUBLIC,
publicKey_);
if (auto member = app_.cluster().member(publicKey_))
{
name_ = *member;
@@ -922,11 +921,23 @@ PeerImp::onMessage (std::shared_ptr <protocol::TMCluster> const& m)
if (node.has_nodename())
name = node.nodename();
app_.cluster().update(
RippleAddress::createNodePublic(node.publickey()),
name,
node.nodeload(),
NetClock::time_point{NetClock::duration{node.reporttime()}});
auto const publicKey = parseBase58<PublicKey>(
TokenType::TOKEN_NODE_PUBLIC, node.publickey());
// NIKB NOTE We should drop the peer immediately if
// they send us a public key we can't parse
if (publicKey)
{
auto const reportTime =
NetClock::time_point{
NetClock::duration{node.reporttime()}};
app_.cluster().update(
*publicKey,
name,
node.nodeload(),
reportTime);
}
}
int loadSources = m->loadsources().size();
@@ -1100,7 +1111,7 @@ PeerImp::onMessage (std::shared_ptr <protocol::TMTransaction> const& m)
flags |= SF_TRUSTED;
}
if (! app_.config().VALIDATION_PRIV.isSet())
if (! app_.config().VALIDATION_PUB.size())
{
// For now, be paranoid and have each validator
// check each transaction, regardless of source
@@ -1240,15 +1251,17 @@ PeerImp::onMessage (std::shared_ptr <protocol::TMProposeSet> const& m)
return;
}
PublicKey const publicKey (makeSlice(set.nodepubkey()));
NetClock::time_point const closeTime { NetClock::duration{set.closetime()} };
Buffer signature (set.signature().data(), set.signature ().size());
uint256 proposeHash, prevLedger;
memcpy (proposeHash.begin (), set.currenttxhash ().data (), 32);
memcpy (prevLedger.begin (), set.previousledger ().data (), 32);
uint256 suppression = proposalUniqueId (
proposeHash, prevLedger, set.proposeseq(),
NetClock::time_point{NetClock::duration{set.closetime()}},
Blob(set.nodepubkey ().begin (), set.nodepubkey ().end ()),
Blob(set.signature ().begin (), set.signature ().end ()));
closeTime, publicKey.slice(), signature);
if (! app_.getHashRouter ().addSuppressionPeer (suppression, id_))
{
@@ -1256,16 +1269,14 @@ PeerImp::onMessage (std::shared_ptr <protocol::TMProposeSet> const& m)
return;
}
RippleAddress signerPublic = RippleAddress::createNodePublic (
strCopy (set.nodepubkey ()));
if (signerPublic == app_.config().VALIDATION_PUB)
if (app_.config().VALIDATION_PUB.size() &&
publicKey == app_.config().VALIDATION_PUB)
{
p_journal_.trace << "Proposal: self";
return;
}
auto const isTrusted = app_.validators().trusted (signerPublic);
auto const isTrusted = app_.validators().trusted (publicKey);
if (!isTrusted)
{
@@ -1286,11 +1297,9 @@ PeerImp::onMessage (std::shared_ptr <protocol::TMProposeSet> const& m)
"Proposal: " << (isTrusted ? "trusted" : "UNTRUSTED");
auto proposal = std::make_shared<LedgerProposal> (
prevLedger, set.proposeseq (), proposeHash,
NetClock::time_point{NetClock::duration{set.closetime()}},
signerPublic, PublicKey(makeSlice(set.nodepubkey())),
suppression);
proposal->setSignature (Blob (set.signature().begin(), set.signature().end()));
prevLedger, set.proposeseq (), proposeHash, closeTime,
publicKey, calcNodeID(publicKey), suppression);
proposal->setSignature (std::move(signature));
std::weak_ptr<PeerImp> weak = shared_from_this();
app_.getJobQueue ().addJob (
@@ -1596,6 +1605,7 @@ PeerImp::onMessage (std::shared_ptr <protocol::TMValidation> const& m)
auto const isTrusted =
app_.validators().trusted(val->getSignerPublic ());
if (!isTrusted && (sanity_.load () == Sanity::insane))
{
p_journal_.debug <<
@@ -1920,7 +1930,7 @@ PeerImp::checkPropose (Job& job,
if (isTrusted)
{
app_.getOPs ().processTrustedProposal (
proposal, packet, publicKey_);
proposal, packet, calcNodeID (publicKey_));
}
else
{

View File

@@ -128,7 +128,7 @@ private:
clock_type::time_point insaneTime_;
bool detaching_ = false;
// Node public key of peer.
RippleAddress publicKey_;
PublicKey publicKey_;
std::string name_;
uint256 sharedValue_;
@@ -172,7 +172,7 @@ public:
/** Create an active incoming peer from an established ssl connection. */
PeerImp (Application& app, id_t id, endpoint_type remote_endpoint,
PeerFinder::Slot::ptr const& slot, beast::http::message&& request,
protocol::TMHello const& hello, RippleAddress const& publicKey,
protocol::TMHello const& hello, PublicKey const& publicKey,
Resource::Consumer consumer,
std::unique_ptr<beast::asio::ssl_bundle>&& ssl_bundle,
OverlayImpl& overlay);
@@ -183,8 +183,8 @@ public:
PeerImp (Application& app, std::unique_ptr<beast::asio::ssl_bundle>&& ssl_bundle,
Buffers const& buffers, PeerFinder::Slot::ptr&& slot,
beast::http::message&& response, Resource::Consumer usage,
protocol::TMHello&& hello,
RippleAddress const& legacyPublicKey, id_t id,
protocol::TMHello const& hello,
PublicKey const& publicKey, id_t id,
OverlayImpl& overlay);
virtual
@@ -270,7 +270,7 @@ public:
void
checkSanity (std::uint32_t seq1, std::uint32_t seq2);
RippleAddress const&
PublicKey const&
getNodePublic () const override
{
return publicKey_;
@@ -477,8 +477,8 @@ template <class Buffers>
PeerImp::PeerImp (Application& app, std::unique_ptr<beast::asio::ssl_bundle>&& ssl_bundle,
Buffers const& buffers, PeerFinder::Slot::ptr&& slot,
beast::http::message&& response, Resource::Consumer usage,
protocol::TMHello&& hello,
RippleAddress const& legacyPublicKey, id_t id,
protocol::TMHello const& hello,
PublicKey const& publicKey, id_t id,
OverlayImpl& overlay)
: Child (overlay)
, app_ (app)
@@ -498,9 +498,9 @@ PeerImp::PeerImp (Application& app, std::unique_ptr<beast::asio::ssl_bundle>&& s
, state_ (State::active)
, sanity_ (Sanity::unknown)
, insaneTime_ (clock_type::now())
, publicKey_ (legacyPublicKey)
, publicKey_ (publicKey)
, creationTime_ (clock_type::now())
, hello_ (std::move(hello))
, hello_ (hello)
, usage_ (usage)
, fee_ (Resource::feeLightPeer)
, slot_ (std::move(slot))

View File

@@ -20,7 +20,6 @@
#include <BeastConfig.h>
#include <ripple/app/ledger/LedgerMaster.h>
#include <ripple/app/main/Application.h>
#include <ripple/app/main/LocalCredentials.h>
#include <ripple/app/misc/NetworkOPs.h>
#include <ripple/core/TimeKeeper.h>
#include <ripple/protocol/digest.h>
@@ -49,8 +48,8 @@ namespace ripple {
@return `true` if successful, `false` otherwise.
*/
static
bool
hashLastMessage (SSL const* ssl, unsigned char* hash,
boost::optional<base_uint<512>>
hashLastMessage (SSL const* ssl,
size_t (*get)(const SSL *, void *buf, size_t))
{
enum
@@ -58,50 +57,42 @@ hashLastMessage (SSL const* ssl, unsigned char* hash,
sslMinimumFinishedLength = 12
};
unsigned char buf[1024];
std::memset(hash, 0, 64);
size_t len = get (ssl, buf, sizeof (buf));
if(len < sslMinimumFinishedLength)
return false;
SHA512 (buf, len, hash);
return true;
return boost::none;
base_uint<512> cookie;
SHA512 (buf, len, cookie.data());
return cookie;
}
std::pair<uint256, bool>
boost::optional<uint256>
makeSharedValue (SSL* ssl, beast::Journal journal)
{
std::pair<uint256, bool> result = { {}, false };
unsigned char sha1[64];
unsigned char sha2[64];
if (!hashLastMessage(ssl, sha1, SSL_get_finished))
auto const cookie1 = hashLastMessage(ssl, SSL_get_finished);
if (!cookie1)
{
journal.error << "Cookie generation: local setup not complete";
return result;
return boost::none;
}
if (!hashLastMessage(ssl, sha2, SSL_get_peer_finished))
auto const cookie2 = hashLastMessage(ssl, SSL_get_peer_finished);
if (!cookie2)
{
journal.error << "Cookie generation: peer setup not complete";
return result;
return boost::none;
}
// If both messages hash to the same value (i.e. match) something is
// wrong. This would cause the resulting cookie to be 0.
if (memcmp (sha1, sha2, sizeof (sha1)) == 0)
auto const result = (*cookie1 ^ *cookie2);
// Both messages hash to the same value and the cookie
// is 0. Don't allow this.
if (result == zero)
{
journal.error << "Cookie generation: identical finished messages";
return result;
return boost::none;
}
for (size_t i = 0; i < sizeof (sha1); ++i)
sha1[i] ^= sha2[i];
// Finally, derive the actual cookie for the values that
// we have calculated.
result.first = sha512Half(Slice(sha1, sizeof(sha1)));
result.second = true;
return result;
return sha512Half (Slice (result.data(), result.size()));
}
protocol::TMHello
@@ -113,17 +104,20 @@ buildHello (
{
protocol::TMHello h;
Blob vchSig;
app.getLocalCredentials ().getNodePrivate ().signNodePrivate (
sharedValue, vchSig);
auto const sig = signDigest (
app.nodeIdentity().first,
app.nodeIdentity().second,
sharedValue);
h.set_protoversion (to_packed (BuildInfo::getCurrentProtocol()));
h.set_protoversionmin (to_packed (BuildInfo::getMinimumProtocol()));
h.set_fullversion (BuildInfo::getFullVersionString ());
h.set_nettime (app.timeKeeper().now().time_since_epoch().count());
h.set_nodepublic (app.getLocalCredentials ().getNodePublic (
).humanNodePublic ());
h.set_nodeproof (&vchSig[0], vchSig.size ());
h.set_nodepublic (
toBase58 (
TokenType::TOKEN_NODE_PUBLIC,
app.nodeIdentity().first));
h.set_nodeproof (sig.data(), sig.size());
// h.set_ipv4port (portNumber); // ignored now
h.set_testnet (false);
@@ -227,24 +221,23 @@ parse_ProtocolVersions (std::string const& s)
return result;
}
std::pair<protocol::TMHello, bool>
boost::optional<protocol::TMHello>
parseHello (beast::http::message const& m, beast::Journal journal)
{
auto const& h = m.headers;
std::pair<protocol::TMHello, bool> result = { {}, false };
protocol::TMHello& hello = result.first;
// protocol version in TMHello is obsolete,
// it is supplanted by the values in the headers.
protocol::TMHello hello;
{
// Required
auto const iter = h.find ("Upgrade");
if (iter == h.end())
return result;
return boost::none;
auto const versions = parse_ProtocolVersions(iter->second);
if (versions.empty())
return result;
return boost::none;
hello.set_protoversion(
(static_cast<std::uint32_t>(versions.back().first) << 16) |
(static_cast<std::uint32_t>(versions.back().second)));
@@ -257,11 +250,11 @@ parseHello (beast::http::message const& m, beast::Journal journal)
// Required
auto const iter = h.find ("Public-Key");
if (iter == h.end())
return result;
RippleAddress addr;
addr.setNodePublic (iter->second);
if (! addr.isValid())
return result;
return boost::none;
auto const pk = parseBase58<PublicKey>(
TokenType::TOKEN_NODE_PUBLIC, iter->second);
if (!pk)
return boost::none;
hello.set_nodepublic (iter->second);
}
@@ -269,7 +262,7 @@ parseHello (beast::http::message const& m, beast::Journal journal)
// Required
auto const iter = h.find ("Session-Signature");
if (iter == h.end())
return result;
return boost::none;
// TODO Security Review
hello.set_nodeproof (beast::base64_decode (iter->second));
}
@@ -287,7 +280,7 @@ parseHello (beast::http::message const& m, beast::Journal journal)
{
std::uint64_t nettime;
if (! beast::lexicalCastChecked(nettime, iter->second))
return result;
return boost::none;
hello.set_nettime (nettime);
}
}
@@ -298,7 +291,7 @@ parseHello (beast::http::message const& m, beast::Journal journal)
{
LedgerIndex ledgerIndex;
if (! beast::lexicalCastChecked(ledgerIndex, iter->second))
return result;
return boost::none;
hello.set_ledgerindex (ledgerIndex);
}
}
@@ -324,7 +317,7 @@ parseHello (beast::http::message const& m, beast::Journal journal)
std::tie (address, valid) =
beast::IP::Address::from_string (iter->second);
if (!valid)
return result;
return boost::none;
if (address.is_v4())
hello.set_local_ip(address.to_v4().value);
}
@@ -339,17 +332,16 @@ parseHello (beast::http::message const& m, beast::Journal journal)
std::tie (address, valid) =
beast::IP::Address::from_string (iter->second);
if (!valid)
return result;
return boost::none;
if (address.is_v4())
hello.set_remote_ip(address.to_v4().value);
}
}
result.second = true;
return result;
return hello;
}
std::pair<RippleAddress, bool>
boost::optional<PublicKey>
verifyHello (protocol::TMHello const& h,
uint256 const& sharedValue,
beast::IP::Address public_ip,
@@ -357,63 +349,69 @@ verifyHello (protocol::TMHello const& h,
beast::Journal journal,
Application& app)
{
std::pair<RippleAddress, bool> result = { {}, false };
auto const ourTime = app.timeKeeper().now().time_since_epoch().count();
std::uint32_t const minTime = ourTime - clockToleranceDeltaSeconds;
std::uint32_t const maxTime = ourTime + clockToleranceDeltaSeconds;
#ifdef BEAST_DEBUG
if (h.has_nettime ())
{
std::int64_t to = ourTime;
to -= h.nettime ();
journal.debug <<
"Connect: time offset " << to;
}
#endif
auto const ourTime = app.timeKeeper().now().time_since_epoch().count();
auto const minTime = ourTime - clockToleranceDeltaSeconds;
auto const maxTime = ourTime + clockToleranceDeltaSeconds;
auto const protocol = BuildInfo::make_protocol(h.protoversion());
if (h.has_nettime () &&
((h.nettime () < minTime) || (h.nettime () > maxTime)))
{
if (h.nettime () > maxTime)
{
journal.info <<
"Clock for is off by +" << h.nettime() - ourTime;
return boost::none;
}
else if (h.nettime () < minTime)
if (h.nettime () < minTime)
{
journal.info <<
"Clock is off by -" << ourTime - h.nettime();
return boost::none;
}
journal.trace <<
"Connect: time offset " <<
static_cast<std::int64_t>(ourTime) - h.nettime();
}
else if (h.protoversionmin () > to_packed (
BuildInfo::getCurrentProtocol()))
if (h.protoversionmin () > to_packed (BuildInfo::getCurrentProtocol()))
{
journal.info <<
"Hello: Disconnect: Protocol mismatch [" <<
"Peer expects " << to_string (protocol) <<
" and we run " << to_string (BuildInfo::getCurrentProtocol()) << "]";
"Peer expects " << to_string (
BuildInfo::make_protocol(h.protoversion())) <<
" and we run " << to_string (
BuildInfo::getCurrentProtocol()) << "]";
return boost::none;
}
else if (! result.first.setNodePublic (h.nodepublic()))
auto const publicKey = parseBase58<PublicKey>(
TokenType::TOKEN_NODE_PUBLIC, h.nodepublic());
if (! publicKey)
{
journal.info <<
"Hello: Disconnect: Bad node public key.";
return boost::none;
}
else if (result.first == app.getLocalCredentials().getNodePublic())
if (*publicKey == app.nodeIdentity().first)
{
journal.info <<
"Hello: Disconnect: Self connection.";
return boost::none;
}
else if (! result.first.verifyNodePublic (
sharedValue, h.nodeproof (), ECDSA::not_strict))
if (! verifyDigest (*publicKey, sharedValue,
makeSlice (h.nodeproof()), false))
{
// Unable to verify they have private key for claimed public key.
journal.info <<
"Hello: Disconnect: Failed to verify session.";
return boost::none;
}
else if (h.has_local_ip () &&
if (h.has_local_ip () &&
is_public (remote) &&
remote.is_v4 () &&
(remote.to_v4().value != h.local_ip ()))
@@ -425,8 +423,10 @@ verifyHello (protocol::TMHello const& h,
beast::IP::to_string (remote.to_v4())
<< " not " <<
beast::IP::to_string (beast::IP::AddressV4 (h.local_ip()));
return boost::none;
}
else if (h.has_remote_ip() && is_public (remote) &&
if (h.has_remote_ip() && is_public (remote) &&
(public_ip != beast::IP::Address()) &&
(h.remote_ip() != public_ip.to_v4().value))
{
@@ -437,13 +437,10 @@ verifyHello (protocol::TMHello const& h,
beast::IP::to_string (public_ip.to_v4())
<< " not " <<
beast::IP::to_string (beast::IP::AddressV4 (h.remote_ip()));
return boost::none;
}
else
{
// Successful connection.
result.second = true;
}
return result;
return publicKey;
}
}

View File

@@ -22,13 +22,14 @@
#include <ripple/app/main/Application.h>
#include <ripple/protocol/BuildInfo.h>
#include <ripple/protocol/RippleAddress.h>
#include <ripple/protocol/PublicKey.h>
#include <ripple/protocol/UintTypes.h>
#include <beast/http/message.h>
#include <beast/utility/Journal.h>
#include <utility>
#include <boost/asio/ssl.hpp>
#include <boost/optional.hpp>
#include "ripple.pb.h"
@@ -47,7 +48,7 @@ enum
If the shared value generation fails, the link MUST be dropped.
@return A pair. Second will be false if shared value generation failed.
*/
std::pair<uint256, bool>
boost::optional<uint256>
makeSharedValue (SSL* ssl, beast::Journal journal);
/** Build a TMHello protocol message. */
@@ -61,16 +62,18 @@ void
appendHello (beast::http::message& m, protocol::TMHello const& hello);
/** Parse HTTP headers into TMHello protocol message.
@return A pair. Second will be false if the parsing failed.
@return A protocol message on success; an empty optional
if the parsing failed.
*/
std::pair<protocol::TMHello, bool>
boost::optional<protocol::TMHello>
parseHello (beast::http::message const& m, beast::Journal journal);
/** Validate and store the public key in the TMHello.
This includes signature verification on the shared value.
@return A pair. Second will be false if the check failed.
@return The remote end public key on success; an empty
optional if the check failed.
*/
std::pair<RippleAddress, bool>
boost::optional<PublicKey>
verifyHello (protocol::TMHello const& h, uint256 const& sharedValue,
beast::IP::Address public_ip,
beast::IP::Endpoint remote,