dns_utils: factor TXT record loading code from checkpoint code

This commit is contained in:
moneromooo-monero 2017-02-16 20:03:26 +00:00
parent 5892f653c7
commit e8a7525ceb
No known key found for this signature in database
GPG key ID: 686F07454D6CEFC3
3 changed files with 110 additions and 104 deletions

View file

@ -37,6 +37,7 @@
#include <stdlib.h> #include <stdlib.h>
#include "include_base_utils.h" #include "include_base_utils.h"
#include <random>
#include <boost/filesystem/fstream.hpp> #include <boost/filesystem/fstream.hpp>
using namespace epee; using namespace epee;
namespace bf = boost::filesystem; namespace bf = boost::filesystem;
@ -451,6 +452,108 @@ std::string get_account_address_as_str_from_url(const std::string& url, bool& dn
return addresses[0]; return addresses[0];
} }
namespace
{
bool dns_records_match(const std::vector<std::string>& a, const std::vector<std::string>& b)
{
if (a.size() != b.size()) return false;
for (const auto& record_in_a : a)
{
bool ok = false;
for (const auto& record_in_b : b)
{
if (record_in_a == record_in_b)
{
ok = true;
break;
}
}
if (!ok) return false;
}
return true;
}
}
bool load_txt_records_from_dns(std::vector<std::string> &good_records, const std::vector<std::string> &dns_urls)
{
std::vector<std::vector<std::string> > records;
records.resize(dns_urls.size());
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<int> dis(0, dns_urls.size() - 1);
size_t first_index = dis(gen);
bool avail, valid;
size_t cur_index = first_index;
do
{
std::string url = dns_urls[cur_index];
records[cur_index] = tools::DNSResolver::instance().get_txt_record(url, avail, valid);
if (!avail)
{
records[cur_index].clear();
LOG_PRINT_L2("DNSSEC not available for checkpoint update at URL: " << url << ", skipping.");
}
if (!valid)
{
records[cur_index].clear();
LOG_PRINT_L2("DNSSEC validation failed for checkpoint update at URL: " << url << ", skipping.");
}
cur_index++;
if (cur_index == dns_urls.size())
{
cur_index = 0;
}
records[cur_index].clear();
} while (cur_index != first_index);
size_t num_valid_records = 0;
for( const auto& record_set : records)
{
if (record_set.size() != 0)
{
num_valid_records++;
}
}
if (num_valid_records < 2)
{
LOG_PRINT_L0("WARNING: no two valid MoneroPulse DNS checkpoint records were received");
return false;
}
int good_records_index = -1;
for (size_t i = 0; i < records.size() - 1; ++i)
{
if (records[i].size() == 0) continue;
for (size_t j = i + 1; j < records.size(); ++j)
{
if (dns_records_match(records[i], records[j]))
{
good_records_index = i;
break;
}
}
if (good_records_index >= 0) break;
}
if (good_records_index < 0)
{
LOG_PRINT_L0("WARNING: no two MoneroPulse DNS checkpoint records matched");
return false;
}
good_records = records[good_records_index];
return true;
}
} // namespace tools::dns_utils } // namespace tools::dns_utils
} // namespace tools } // namespace tools

View file

@ -165,6 +165,8 @@ std::vector<std::string> addresses_from_url(const std::string& url, bool& dnssec
std::string get_account_address_as_str_from_url(const std::string& url, bool& dnssec_valid); std::string get_account_address_as_str_from_url(const std::string& url, bool& dnssec_valid);
bool load_txt_records_from_dns(std::vector<std::string> &records, const std::vector<std::string> &dns_urls);
} // namespace tools::dns_utils } // namespace tools::dns_utils
} // namespace tools } // namespace tools

View file

@ -42,30 +42,6 @@ using namespace epee;
#undef MONERO_DEFAULT_LOG_CATEGORY #undef MONERO_DEFAULT_LOG_CATEGORY
#define MONERO_DEFAULT_LOG_CATEGORY "checkpoints" #define MONERO_DEFAULT_LOG_CATEGORY "checkpoints"
namespace
{
bool dns_records_match(const std::vector<std::string>& a, const std::vector<std::string>& b)
{
if (a.size() != b.size()) return false;
for (const auto& record_in_a : a)
{
bool ok = false;
for (const auto& record_in_b : b)
{
if (record_in_a == record_in_b)
{
ok = true;
break;
}
}
if (!ok) return false;
}
return true;
}
} // anonymous namespace
namespace cryptonote namespace cryptonote
{ {
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@ -230,6 +206,8 @@ namespace cryptonote
bool checkpoints::load_checkpoints_from_dns(bool testnet) bool checkpoints::load_checkpoints_from_dns(bool testnet)
{ {
std::vector<std::string> records;
// All four MoneroPulse domains have DNSSEC on and valid // All four MoneroPulse domains have DNSSEC on and valid
static const std::vector<std::string> dns_urls = { "checkpoints.moneropulse.se" static const std::vector<std::string> dns_urls = { "checkpoints.moneropulse.se"
, "checkpoints.moneropulse.org" , "checkpoints.moneropulse.org"
@ -243,87 +221,10 @@ namespace cryptonote
, "testpoints.moneropulse.co" , "testpoints.moneropulse.co"
}; };
std::vector<std::vector<std::string> > records; if (!tools::dns_utils::load_txt_records_from_dns(records, testnet ? testnet_dns_urls : dns_urls))
records.resize(dns_urls.size()); return true; // why true ?
std::random_device rd; for (const auto& record : records)
std::mt19937 gen(rd());
std::uniform_int_distribution<int> dis(0, dns_urls.size() - 1);
size_t first_index = dis(gen);
bool avail, valid;
size_t cur_index = first_index;
do
{
std::string url;
if (testnet)
{
url = testnet_dns_urls[cur_index];
}
else
{
url = dns_urls[cur_index];
}
records[cur_index] = tools::DNSResolver::instance().get_txt_record(url, avail, valid);
if (!avail)
{
records[cur_index].clear();
LOG_PRINT_L2("DNSSEC not available for checkpoint update at URL: " << url << ", skipping.");
}
if (!valid)
{
records[cur_index].clear();
LOG_PRINT_L2("DNSSEC validation failed for checkpoint update at URL: " << url << ", skipping.");
}
cur_index++;
if (cur_index == dns_urls.size())
{
cur_index = 0;
}
records[cur_index].clear();
} while (cur_index != first_index);
size_t num_valid_records = 0;
for( const auto& record_set : records)
{
if (record_set.size() != 0)
{
num_valid_records++;
}
}
if (num_valid_records < 2)
{
LOG_PRINT_L0("WARNING: no two valid MoneroPulse DNS checkpoint records were received");
return true;
}
int good_records_index = -1;
for (size_t i = 0; i < records.size() - 1; ++i)
{
if (records[i].size() == 0) continue;
for (size_t j = i + 1; j < records.size(); ++j)
{
if (dns_records_match(records[i], records[j]))
{
good_records_index = i;
break;
}
}
if (good_records_index >= 0) break;
}
if (good_records_index < 0)
{
LOG_PRINT_L0("WARNING: no two MoneroPulse DNS checkpoint records matched");
return true;
}
for (auto& record : records[good_records_index])
{ {
auto pos = record.find(":"); auto pos = record.find(":");
if (pos != std::string::npos) if (pos != std::string::npos)