mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-06 17:27:55 +00:00
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:
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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] =
|
||||
|
||||
@@ -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>&&)
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user