Add [validator_list_threshold] to validators.txt to improve UNL security (#5112)

This commit is contained in:
Bronek Kozicki
2025-01-23 23:00:34 +00:00
committed by GitHub
parent 3868c04e99
commit 5fbee8c824
11 changed files with 2129 additions and 49 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -22,6 +22,7 @@
#include <xrpld/core/Config.h>
#include <xrpld/core/ConfigSections.h>
#include <xrpl/basics/contract.h>
#include <xrpl/beast/unit_test/suite.h>
#include <xrpl/server/Port.h>
#include <boost/filesystem.hpp>
#include <boost/format.hpp>
@@ -222,6 +223,9 @@ moreripplevalidators.net
[validator_list_keys]
03E74EE14CB525AFBB9F1B7D86CD58ECC4B91452294B42AB4E78F260BD905C091D
030775A669685BD6ABCEBD80385921C7851783D991A8055FD21D2F3966C96F1B56
[validator_list_threshold]
2
)rippleConfig");
return configContents;
}
@@ -538,6 +542,7 @@ nHBu9PTL9dn2GuZtdW4U2WzBwffyX9qsQCd9CNU4Z5YG3PQfViM8
c.loadFromString(toLoad);
BEAST_EXPECT(c.legacy("validators_file").empty());
BEAST_EXPECT(c.section(SECTION_VALIDATORS).values().size() == 5);
BEAST_EXPECT(c.VALIDATOR_LIST_THRESHOLD == std::nullopt);
}
{
// load validator list sites and keys from config
@@ -549,6 +554,9 @@ trustthesevalidators.gov
[validator_list_keys]
021A99A537FDEBC34E4FCA03B39BEADD04299BB19E85097EC92B15A3518801E566
[validator_list_threshold]
1
)rippleConfig");
c.loadFromString(toLoad);
BEAST_EXPECT(
@@ -565,6 +573,133 @@ trustthesevalidators.gov
c.section(SECTION_VALIDATOR_LIST_KEYS).values()[0] ==
"021A99A537FDEBC34E4FCA03B39BEADD04299BB19E85097EC92B15A3518801"
"E566");
BEAST_EXPECT(
c.section(SECTION_VALIDATOR_LIST_THRESHOLD).values().size() ==
1);
BEAST_EXPECT(
c.section(SECTION_VALIDATOR_LIST_THRESHOLD).values()[0] == "1");
BEAST_EXPECT(c.VALIDATOR_LIST_THRESHOLD == std::size_t(1));
}
{
// load validator list sites and keys from config
Config c;
std::string toLoad(R"rippleConfig(
[validator_list_sites]
ripplevalidators.com
trustthesevalidators.gov
[validator_list_keys]
021A99A537FDEBC34E4FCA03B39BEADD04299BB19E85097EC92B15A3518801E566
[validator_list_threshold]
0
)rippleConfig");
c.loadFromString(toLoad);
BEAST_EXPECT(
c.section(SECTION_VALIDATOR_LIST_SITES).values().size() == 2);
BEAST_EXPECT(
c.section(SECTION_VALIDATOR_LIST_SITES).values()[0] ==
"ripplevalidators.com");
BEAST_EXPECT(
c.section(SECTION_VALIDATOR_LIST_SITES).values()[1] ==
"trustthesevalidators.gov");
BEAST_EXPECT(
c.section(SECTION_VALIDATOR_LIST_KEYS).values().size() == 1);
BEAST_EXPECT(
c.section(SECTION_VALIDATOR_LIST_KEYS).values()[0] ==
"021A99A537FDEBC34E4FCA03B39BEADD04299BB19E85097EC92B15A3518801"
"E566");
BEAST_EXPECT(
c.section(SECTION_VALIDATOR_LIST_THRESHOLD).values().size() ==
1);
BEAST_EXPECT(
c.section(SECTION_VALIDATOR_LIST_THRESHOLD).values()[0] == "0");
BEAST_EXPECT(c.VALIDATOR_LIST_THRESHOLD == std::nullopt);
}
{
// load should throw if [validator_list_threshold] is greater than
// the number of [validator_list_keys]
Config c;
std::string toLoad(R"rippleConfig(
[validator_list_sites]
ripplevalidators.com
trustthesevalidators.gov
[validator_list_keys]
021A99A537FDEBC34E4FCA03B39BEADD04299BB19E85097EC92B15A3518801E566
[validator_list_threshold]
2
)rippleConfig");
std::string error;
auto const expectedError =
"Value in config section [validator_list_threshold] exceeds "
"the number of configured list keys";
try
{
c.loadFromString(toLoad);
fail();
}
catch (std::runtime_error& e)
{
error = e.what();
}
BEAST_EXPECT(error == expectedError);
}
{
// load should throw if [validator_list_threshold] is malformed
Config c;
std::string toLoad(R"rippleConfig(
[validator_list_sites]
ripplevalidators.com
trustthesevalidators.gov
[validator_list_keys]
021A99A537FDEBC34E4FCA03B39BEADD04299BB19E85097EC92B15A3518801E566
[validator_list_threshold]
value = 2
)rippleConfig");
std::string error;
auto const expectedError =
"Config section [validator_list_threshold] should contain "
"single value only";
try
{
c.loadFromString(toLoad);
fail();
}
catch (std::runtime_error& e)
{
error = e.what();
}
BEAST_EXPECT(error == expectedError);
}
{
// load should throw if [validator_list_threshold] is negative
Config c;
std::string toLoad(R"rippleConfig(
[validator_list_sites]
ripplevalidators.com
trustthesevalidators.gov
[validator_list_keys]
021A99A537FDEBC34E4FCA03B39BEADD04299BB19E85097EC92B15A3518801E566
[validator_list_threshold]
-1
)rippleConfig");
bool error = false;
try
{
c.loadFromString(toLoad);
fail();
}
catch (std::bad_cast& e)
{
error = true;
}
BEAST_EXPECT(error);
}
{
// load should throw if [validator_list_sites] is configured but
@@ -581,6 +716,7 @@ trustthesevalidators.gov
try
{
c.loadFromString(toLoad);
fail();
}
catch (std::runtime_error& e)
{
@@ -602,6 +738,10 @@ trustthesevalidators.gov
c.section(SECTION_VALIDATOR_LIST_SITES).values().size() == 2);
BEAST_EXPECT(
c.section(SECTION_VALIDATOR_LIST_KEYS).values().size() == 2);
BEAST_EXPECT(
c.section(SECTION_VALIDATOR_LIST_THRESHOLD).values().size() ==
1);
BEAST_EXPECT(c.VALIDATOR_LIST_THRESHOLD == 2);
}
{
// load from specified [validators_file] file name
@@ -620,6 +760,10 @@ trustthesevalidators.gov
c.section(SECTION_VALIDATOR_LIST_SITES).values().size() == 2);
BEAST_EXPECT(
c.section(SECTION_VALIDATOR_LIST_KEYS).values().size() == 2);
BEAST_EXPECT(
c.section(SECTION_VALIDATOR_LIST_THRESHOLD).values().size() ==
1);
BEAST_EXPECT(c.VALIDATOR_LIST_THRESHOLD == 2);
}
{
// load from specified [validators_file] relative path
@@ -638,6 +782,10 @@ trustthesevalidators.gov
c.section(SECTION_VALIDATOR_LIST_SITES).values().size() == 2);
BEAST_EXPECT(
c.section(SECTION_VALIDATOR_LIST_KEYS).values().size() == 2);
BEAST_EXPECT(
c.section(SECTION_VALIDATOR_LIST_THRESHOLD).values().size() ==
1);
BEAST_EXPECT(c.VALIDATOR_LIST_THRESHOLD == 2);
}
{
// load from validators file in default location
@@ -654,6 +802,10 @@ trustthesevalidators.gov
c.section(SECTION_VALIDATOR_LIST_SITES).values().size() == 2);
BEAST_EXPECT(
c.section(SECTION_VALIDATOR_LIST_KEYS).values().size() == 2);
BEAST_EXPECT(
c.section(SECTION_VALIDATOR_LIST_THRESHOLD).values().size() ==
1);
BEAST_EXPECT(c.VALIDATOR_LIST_THRESHOLD == 2);
}
{
// load from specified [validators_file] instead
@@ -674,6 +826,10 @@ trustthesevalidators.gov
c.section(SECTION_VALIDATOR_LIST_SITES).values().size() == 2);
BEAST_EXPECT(
c.section(SECTION_VALIDATOR_LIST_KEYS).values().size() == 2);
BEAST_EXPECT(
c.section(SECTION_VALIDATOR_LIST_THRESHOLD).values().size() ==
1);
BEAST_EXPECT(c.VALIDATOR_LIST_THRESHOLD == 2);
}
{
@@ -711,6 +867,39 @@ trustthesevalidators.gov
c.section(SECTION_VALIDATOR_LIST_SITES).values().size() == 4);
BEAST_EXPECT(
c.section(SECTION_VALIDATOR_LIST_KEYS).values().size() == 3);
BEAST_EXPECT(
c.section(SECTION_VALIDATOR_LIST_THRESHOLD).values().size() ==
1);
BEAST_EXPECT(c.VALIDATOR_LIST_THRESHOLD == 2);
}
{
// load should throw if [validator_list_threshold] is present both
// in rippled cfg and validators file
boost::format cc(R"rippleConfig(
[validators_file]
%1%
[validator_list_threshold]
1
)rippleConfig");
std::string error;
detail::ValidatorsTxtGuard const vtg(
*this, "test_cfg", "validators.cfg");
BEAST_EXPECT(vtg.validatorsFileExists());
auto const expectedError =
"Config section [validator_list_threshold] should contain "
"single value only";
try
{
Config c;
c.loadFromString(boost::str(cc % vtg.validatorsFile()));
fail();
}
catch (std::runtime_error& e)
{
error = e.what();
}
BEAST_EXPECT(error == expectedError);
}
{
// load should throw if [validators], [validator_keys] and