20 #include <ripple/app/misc/Manifest.h>
21 #include <ripple/basics/Log.h>
22 #include <ripple/basics/StringUtilities.h>
23 #include <ripple/basics/base64.h>
24 #include <ripple/basics/contract.h>
25 #include <ripple/beast/rfc2616.h>
26 #include <ripple/core/DatabaseCon.h>
27 #include <ripple/json/json_reader.h>
28 #include <ripple/protocol/PublicKey.h>
29 #include <ripple/protocol/Sign.h>
30 #include <boost/algorithm/clamp.hpp>
31 #include <boost/regex.hpp>
37 boost::optional<Manifest>
73 st.applyTemplate(manifestFormat);
91 auto const d = st.getFieldVL(
sfDomain);
94 if (boost::algorithm::clamp(d.size(), 4, 128) != d.size())
97 m.
domain.
assign(
reinterpret_cast<char const*
>(d.data()), d.size());
103 static boost::regex
const re(
114 boost::regex_constants::optimize);
116 if (!boost::regex_match(m.
domain, re))
121 bool const hasEphemeralSig = st.isFieldPresent(
sfSignature);
137 if (!hasEphemeralKey)
140 if (!hasEphemeralSig)
159 template <
class Stream>
167 s <<
"Manifest: " << action
173 template <
class Stream>
182 s <<
"Manifest: " << action
184 <<
";OldSeq: " << oldSeq <<
";";
223 boost::optional<Blob>
243 boost::optional<ValidatorToken>
255 return init + s.size();
258 for (
auto const& line : blob)
266 if (r.
parse(tokenStr, token))
271 if (m.isString() && k.isString())
273 auto const key =
strUnHex(k.asString());
275 if (key && key->size() == 32)
292 auto const iter =
map_.find(pk);
294 if (iter !=
map_.end() && !iter->second.revoked())
295 return iter->second.signingKey;
312 boost::optional<std::uint32_t>
316 auto const iter =
map_.find(pk);
318 if (iter !=
map_.end() && !iter->second.revoked())
319 return iter->second.sequence;
324 boost::optional<std::string>
328 auto const iter =
map_.find(pk);
330 if (iter !=
map_.end() && !iter->second.revoked())
331 return iter->second.domain;
336 boost::optional<std::string>
340 auto const iter =
map_.find(pk);
342 if (iter !=
map_.end() && !iter->second.revoked())
343 return iter->second.serialized;
352 auto const iter =
map_.find(pk);
354 if (iter !=
map_.end())
355 return iter->second.revoked();
371 if (iter !=
map_.end() && m.
sequence <= iter->second.sequence)
385 iter->second.sequence);
395 if (
auto stream =
j_.
warn())
413 if (
auto stream =
j_.
warn())
417 if (iter ==
map_.end())
424 if (
auto stream =
j_.
info())
431 map_.emplace(std::move(masterKey), std::move(m));
439 if (
auto stream =
j_.
info())
445 iter->second.sequence);
452 iter->second = std::move(m);
462 std::string const sql =
"SELECT RawData FROM " + dbTable +
";";
464 soci::blob sociRawData(*db);
465 soci::statement st = (db->prepare << sql, soci::into(sociRawData));
470 convert(sociRawData, serialized);
475 JLOG(
j_.
warn()) <<
"Unverifiable manifest in db";
483 JLOG(
j_.
warn()) <<
"Malformed manifest in database";
495 load(dbCon, dbTable);
497 if (!configManifest.
empty())
502 JLOG(
j_.
error()) <<
"Malformed validator_token in config";
508 JLOG(
j_.
warn()) <<
"Configured manifest revokes public key";
513 JLOG(
j_.
error()) <<
"Manifest in config was rejected";
518 if (!configRevocation.
empty())
522 configRevocation.
cbegin(),
523 configRevocation.
cend(),
526 return init + s.size();
529 for (
auto const& line : configRevocation)
534 if (!mo || !mo->revoked() ||
537 JLOG(
j_.
error()) <<
"Invalid validator key revocation in config";
555 soci::transaction tr(*db);
556 *db <<
"DELETE FROM " << dbTable;
558 "INSERT INTO " + dbTable +
" (RawData) VALUES (:rawData);";
559 for (
auto const& v :
map_)
563 if (!v.second.revoked() && !isTrusted(v.second.masterKey))
565 JLOG(
j_.
info()) <<
"Untrusted manifest in cache not saved to db";
572 soci::blob rawData(*db);
573 convert(v.second.serialized, rawData);
574 *db << sql, soci::use(rawData);
std::size_t size() const noexcept
Returns the number of bytes in the storage.
void save(DatabaseCon &dbCon, std::string const &dbTable, std::function< bool(PublicKey const &)> isTrusted)
Save cached manifests to database.
std::string domain
The domain, if one was specified in the manifest; empty otherwise.
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)
PublicKey getMasterKey(PublicKey const &pk) const
Returns ephemeral signing key's master public key.
const SField sfGeneric(access, 0)
boost::optional< KeyType > publicKeyType(Slice const &slice)
Returns the type of public key.
An immutable linear range of bytes.
void convert(soci::blob &from, std::vector< std::uint8_t > &to)
const SF_Blob sfSigningPubKey(access, STI_VL, 3, "SigningPubKey")
Value get(UInt index, const Value &defaultValue) const
If the array contains at least index+1 elements, returns the element value, otherwise returns default...
PublicKey signingKey
The ephemeral key associated with this manifest.
std::string serialized
The manifest in serialized form.
const SF_U32 sfSequence(access, STI_UINT32, 4, "Sequence")
PublicKey masterKey
The master key associated with this manifest.
bool verify() const
Returns true if manifest signature is valid.
const SF_Blob sfMasterSignature(access, STI_VL, 18, "MasterSignature", SField::sMD_Default, SField::notSigning)
std::string toBase58(AccountID const &v)
Convert AccountID to base58 checked string.
std::uint8_t const * data() const noexcept
Return a pointer to beginning of the storage.
hash_map< PublicKey, Manifest > map_
Active manifests stored by master public key.
boost::optional< Blob > strUnHex(std::size_t strSize, Iterator begin, Iterator end)
Blob getFieldVL(SField const &field) const
Unserialize a JSON document into a Value.
bool empty() const noexcept
Return true if the byte range is empty.
const SF_Blob sfSignature(access, STI_VL, 6, "Signature", SField::sMD_Default, SField::notSigning)
bool revoked() const
Returns true if manifest revokes master key.
std::pair< FwdIter, FwdIter > trim(FwdIter first, FwdIter last)
bool verify(PublicKey const &publicKey, Slice const &m, Slice const &sig, bool mustBeFullyCanonical)
Verify a signature on a message.
boost::optional< Blob > getSignature() const
Returns manifest signature.
Defines the fields and their attributes within a STObject.
LockedSociSession checkoutDb()
hash_map< PublicKey, PublicKey > signingToMasterKeys_
Master public keys stored by current ephemeral public key.
bool revoked(PublicKey const &pk) const
Returns true if master key has been revoked in a manifest.
boost::optional< std::string > getManifest(PublicKey const &pk) const
Returns mainfest corresponding to a given public key.
std::string base64_decode(std::string const &data)
PublicKey getSigningKey(PublicKey const &pk) const
Returns master key's current signing key.
Blob getMasterSignature() const
Returns manifest master key signature.
@ invalid
Timely, but invalid signature.
const SF_U16 sfVersion(access, STI_UINT16, 16, "Version")
@ accepted
Manifest is valid.
std::uint32_t sequence
The sequence number of this manifest.
const SF_Blob sfPublicKey(access, STI_VL, 1, "PublicKey")
@ stale
Sequence is too old.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
boost::optional< Manifest > deserializeManifest(Slice s)
Constructs Manifest from serialized string.
boost::optional< ValidatorToken > loadValidatorToken(std::vector< std::string > const &blob)
Stream & logMftAct(Stream &s, std::string const &action, PublicKey const &pk, std::uint32_t seq)
bool parse(std::string const &document, Value &root)
Read a Value from a JSON document.
uint256 hash() const
Returns hash of serialized manifest data.
boost::optional< std::uint32_t > getSequence(PublicKey const &pk) const
Returns master key's current manifest sequence.
bool load(DatabaseCon &dbCon, std::string const &dbTable, std::string const &configManifest, std::vector< std::string > const &configRevocation)
Populate manifest cache with manifests in database and config.
ManifestDisposition applyManifest(Manifest m)
Add manifest to cache.
void set(const SOTemplate &)
boost::optional< std::string > getDomain(PublicKey const &pk) const
Returns domain claimed by a given public key.
T & get(EitherAmount &amt)
uint256 getHash(HashPrefix prefix) const
const SF_Blob sfDomain(access, STI_VL, 7, "Domain")