From e8a7525cebf5c8b00aa3cffa14221640acaa43f3 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Thu, 16 Feb 2017 20:03:26 +0000 Subject: [PATCH] dns_utils: factor TXT record loading code from checkpoint code --- src/common/dns_utils.cpp | 103 +++++++++++++++++++++++++ src/common/dns_utils.h | 2 + src/cryptonote_basic/checkpoints.cpp | 109 ++------------------------- 3 files changed, 110 insertions(+), 104 deletions(-) diff --git a/src/common/dns_utils.cpp b/src/common/dns_utils.cpp index 5ff39574c..4feab16f3 100644 --- a/src/common/dns_utils.cpp +++ b/src/common/dns_utils.cpp @@ -37,6 +37,7 @@ #include #include "include_base_utils.h" +#include #include using namespace epee; 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]; } +namespace +{ + bool dns_records_match(const std::vector& a, const std::vector& 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 &good_records, const std::vector &dns_urls) +{ + std::vector > records; + records.resize(dns_urls.size()); + + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution 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 diff --git a/src/common/dns_utils.h b/src/common/dns_utils.h index 6ecf5595c..2e881f0e0 100644 --- a/src/common/dns_utils.h +++ b/src/common/dns_utils.h @@ -165,6 +165,8 @@ std::vector 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); +bool load_txt_records_from_dns(std::vector &records, const std::vector &dns_urls); + } // namespace tools::dns_utils } // namespace tools diff --git a/src/cryptonote_basic/checkpoints.cpp b/src/cryptonote_basic/checkpoints.cpp index 3cf804ede..1e7754886 100644 --- a/src/cryptonote_basic/checkpoints.cpp +++ b/src/cryptonote_basic/checkpoints.cpp @@ -42,30 +42,6 @@ using namespace epee; #undef MONERO_DEFAULT_LOG_CATEGORY #define MONERO_DEFAULT_LOG_CATEGORY "checkpoints" -namespace -{ - bool dns_records_match(const std::vector& a, const std::vector& 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 { //--------------------------------------------------------------------------- @@ -230,6 +206,8 @@ namespace cryptonote bool checkpoints::load_checkpoints_from_dns(bool testnet) { + std::vector records; + // All four MoneroPulse domains have DNSSEC on and valid static const std::vector dns_urls = { "checkpoints.moneropulse.se" , "checkpoints.moneropulse.org" @@ -243,87 +221,10 @@ namespace cryptonote , "testpoints.moneropulse.co" }; - std::vector > records; - records.resize(dns_urls.size()); + if (!tools::dns_utils::load_txt_records_from_dns(records, testnet ? testnet_dns_urls : dns_urls)) + return true; // why true ? - std::random_device rd; - std::mt19937 gen(rd()); - std::uniform_int_distribution 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]) + for (const auto& record : records) { auto pos = record.find(":"); if (pos != std::string::npos)