20 #include <ripple/app/ledger/LedgerMaster.h>
21 #include <ripple/app/main/Application.h>
22 #include <ripple/basics/base64.h>
23 #include <ripple/basics/safe_cast.h>
24 #include <ripple/beast/core/LexicalCast.h>
25 #include <ripple/beast/rfc2616.h>
26 #include <ripple/overlay/impl/Handshake.h>
27 #include <ripple/protocol/digest.h>
28 #include <boost/regex.hpp>
39 boost::beast::http::fields
const& headers,
42 auto const header = headers.find(
"X-Protocol-Ctl");
43 if (header == headers.end())
46 boost::regex rx(feature +
"=([^;\\s]+)");
47 auto const value = header->value().to_string();
48 if (boost::regex_search(value, match, rx))
55 boost::beast::http::fields
const& headers,
67 boost::beast::http::fields
const& headers,
76 bool ledgerReplayEnabled,
77 bool txReduceRelayEnabled,
78 bool vpReduceRelayEnabled)
83 if (ledgerReplayEnabled)
85 if (txReduceRelayEnabled)
87 if (vpReduceRelayEnabled)
96 bool ledgerReplayEnabled,
97 bool txReduceRelayEnabled,
98 bool vpReduceRelayEnabled)
129 constexpr
std::size_t sslMinimumFinishedLength = 12;
131 unsigned char buf[1024];
132 size_t len =
get(ssl, buf,
sizeof(buf));
134 if (len < sslMinimumFinishedLength)
140 SHA512(buf, len, cookie.
data());
147 auto const cookie1 =
hashLastMessage(ssl.native_handle(), SSL_get_finished);
150 JLOG(journal.
error()) <<
"Cookie generation: local setup not complete";
158 JLOG(journal.
error()) <<
"Cookie generation: peer setup not complete";
162 auto const result = (*cookie1 ^ *cookie2);
166 if (result == beast::zero)
168 JLOG(journal.
error())
169 <<
"Cookie generation: identical finished messages";
178 boost::beast::http::fields& h,
204 h.insert(
"Session-Signature",
base64_encode(sig.data(), sig.size()));
213 h.insert(
"Remote-IP", remote_ip.to_string());
215 if (!public_ip.is_unspecified())
216 h.insert(
"Local-IP", public_ip.to_string());
220 h.insert(
"Closed-Ledger",
strHex(cl->info().hash));
221 h.insert(
"Previous-Ledger",
strHex(cl->info().parentHash));
227 boost::beast::http::fields
const& headers,
234 if (
auto const iter = headers.find(
"Server-Domain"); iter != headers.end())
240 if (
auto const iter = headers.find(
"Network-ID"); iter != headers.end())
247 if (networkID && nid != *networkID)
251 if (
auto const iter = headers.find(
"Network-Time"); iter != headers.end())
255 TimeKeeper::duration::rep val;
268 auto const tolerance = 20s;
276 return duration_cast<std::chrono::seconds>(a - b);
277 return -duration_cast<std::chrono::seconds>(b - a);
280 auto const offset = calculateOffset(netTime, ourTime);
282 if (
abs(offset) > tolerance)
287 if (
auto const iter = headers.find(
"Public-Key"); iter != headers.end())
289 auto pk = parseBase58<PublicKey>(
311 auto const iter = headers.find(
"Session-Signature");
313 if (iter == headers.end())
325 if (
auto const iter = headers.find(
"Local-IP"); iter != headers.end())
327 boost::system::error_code ec;
328 auto const local_ip = boost::asio::ip::address::from_string(
329 iter->value().to_string(), ec);
336 "Incorrect Local-IP: " + remote.to_string() +
" instead of " +
337 local_ip.to_string());
340 if (
auto const iter = headers.find(
"Remote-IP"); iter != headers.end())
342 boost::system::error_code ec;
343 auto const remote_ip = boost::asio::ip::address::from_string(
344 iter->value().to_string(), ec);
354 if (remote_ip != public_ip)
356 "Incorrect Remote-IP: " + public_ip.to_string() +
357 " instead of " + remote_ip.to_string());
368 bool ledgerReplayEnabled,
369 bool txReduceRelayEnabled,
373 m.method(boost::beast::http::verb::get);
378 m.insert(
"Connection",
"Upgrade");
379 m.insert(
"Connect-As",
"Peer");
380 m.insert(
"Crawl", crawlPublic ?
"public" :
"private");
386 txReduceRelayEnabled,
387 vpReduceRelayEnabled));
403 resp.result(boost::beast::http::status::switching_protocols);
404 resp.version(req.version());
405 resp.insert(
"Connection",
"Upgrade");
407 resp.insert(
"Connect-As",
"Peer");
409 resp.insert(
"Crawl", crawlPublic ?
"public" :
"private");
419 buildHandshake(resp, sharedValue, networkID, public_ip, remote_ip, app);
static std::optional< base_uint< 512 > > hashLastMessage(SSL const *ssl, size_t(*get)(const SSL *, void *, size_t))
Hashes the latest finished message from an SSL stream.
std::enable_if_t< std::is_same< T, char >::value||std::is_same< T, unsigned char >::value, Slice > makeSlice(std::array< T, N > const &a)
An immutable linear range of bytes.
virtual std::uint64_t instanceID() const =0
Returns a 64-bit instance identifier, generated at startup.
static constexpr char DELIM_FEATURE[]
std::string makeFeaturesRequestHeader(bool comprEnabled, bool ledgerReplayEnabled, bool txReduceRelayEnabled, bool vpReduceRelayEnabled)
Make request header X-Protocol-Ctl value with supported features.
std::string base64_encode(std::uint8_t const *data, std::size_t len)
static constexpr char FEATURE_LEDGER_REPLAY[]
std::string toBase58(AccountID const &v)
Convert AccountID to base58 checked string.
std::optional< uint256 > makeSharedValue(stream_type &ssl, beast::Journal journal)
Computes a shared value based on the SSL connection state.
virtual TimeKeeper & timeKeeper()=0
static constexpr char FEATURE_VPRR[]
bool isFeatureValue(boost::beast::http::fields const &headers, std::string const &feature, std::string const &value)
Check if a feature's value is equal to the specified value.
static constexpr char FEATURE_TXRR[]
bool featureEnabled(boost::beast::http::fields const &headers, std::string const &feature)
Check if a feature is enabled.
std::optional< KeyType > publicKeyType(Slice const &slice)
Returns the type of public key.
Integers of any length that is a multiple of 32-bits.
boost::asio::ip::address Address
virtual LedgerMaster & getLedgerMaster()=0
Buffer signDigest(PublicKey const &pk, SecretKey const &sk, uint256 const &digest)
Generate a signature for a message digest.
virtual Config & config()=0
virtual std::pair< PublicKey, SecretKey > const & nodeIdentity()=0
static constexpr char FEATURE_COMPR[]
std::string base64_decode(std::string const &data)
A generic endpoint for log messages.
bool is_public(AddressV4 const &addr)
Returns true if the address is a public routable address.
std::optional< std::string > getFeatureValue(boost::beast::http::fields const &headers, std::string const &feature)
Get feature's header value.
boost::beast::ssl_stream< socket_type > stream_type
bool VP_REDUCE_RELAY_ENABLE
std::string const & getFullVersionString()
Full server version string.
std::string const & supportedProtocolVersions()
The list of all the protocol versions we support.
std::shared_ptr< Ledger const > getClosedLedger()
bool token_in_list(boost::string_ref const &value, boost::string_ref const &token)
Returns true if the specified token exists in the list.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
constexpr Number abs(Number x) noexcept
std::string SERVER_DOMAIN
bool lexicalCastChecked(Out &out, In in)
Intelligently convert from one type to another.
bool verifyDigest(PublicKey const &publicKey, uint256 const &digest, Slice const &sig, bool mustBeFullyCanonical) noexcept
Verify a secp256k1 signature on the digest of a message.
sha512_half_hasher::result_type sha512Half(Args const &... args)
Returns the SHA512-Half of a series of objects.
virtual time_point now() const override=0
Returns the estimate of wall time, in network time.
boost::beast::http::request< boost::beast::http::empty_body > request_type
std::string to_string(Manifest const &m)
Format the specified manifest to a string for debugging purposes.
bool isProperlyFormedTomlDomain(std::string const &domain)
Determines if the given string looks like a TOML-file hosting domain.
std::string strHex(FwdIt begin, FwdIt end)
bool TX_REDUCE_RELAY_ENABLE
PublicKey verifyHandshake(boost::beast::http::fields const &headers, ripple::uint256 const &sharedValue, std::optional< std::uint32_t > networkID, beast::IP::Address public_ip, beast::IP::Address remote, Application &app)
Validate header fields necessary for upgrading the link to the peer protocol.
std::string makeFeaturesResponseHeader(http_request_type const &headers, bool comprEnabled, bool ledgerReplayEnabled, bool txReduceRelayEnabled, bool vpReduceRelayEnabled)
Make response header X-Protocol-Ctl value with supported features.
auto makeRequest(bool crawlPublic, bool comprEnabled, bool ledgerReplayEnabled, bool txReduceRelayEnabled, bool vpReduceRelayEnabled) -> request_type
Make outbound http request.
http_response_type makeResponse(bool crawlPublic, http_request_type const &req, beast::IP::Address public_ip, beast::IP::Address remote_ip, uint256 const &sharedValue, std::optional< std::uint32_t > networkID, ProtocolVersion protocol, Application &app)
Make http response.
bool is_unspecified(Address const &addr)
Returns true if the address is unspecified.
boost::beast::http::request< boost::beast::http::dynamic_body > http_request_type
typename NetClock ::time_point time_point
boost::beast::http::response< boost::beast::http::dynamic_body > http_response_type
typename NetClock ::duration duration
T & get(EitherAmount &amt)
void buildHandshake(boost::beast::http::fields &h, ripple::uint256 const &sharedValue, std::optional< std::uint32_t > networkID, beast::IP::Address public_ip, beast::IP::Address remote_ip, Application &app)
Insert fields headers necessary for upgrading the link to the peer protocol.