Skip to content

Commit

Permalink
Merge pull request #177 from stoffu/aeon-dns
Browse files Browse the repository at this point in the history
Upstream merges related to DNS
  • Loading branch information
aeonix authored May 23, 2020
2 parents 4dd206a + dc714d3 commit c3763a1
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 22 deletions.
104 changes: 84 additions & 20 deletions src/common/dns_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#include <boost/thread/mutex.hpp>
#include <boost/thread/thread.hpp>
#include <boost/algorithm/string/join.hpp>
#include <boost/optional.hpp>
using namespace epee;
namespace bf = boost::filesystem;

Expand All @@ -46,10 +47,10 @@ namespace bf = boost::filesystem;
static const char *DEFAULT_DNS_PUBLIC_ADDR[] =
{
"194.150.168.168", // CCC (Germany)
"81.3.27.54", // Lightning Wire Labs (Germany)
"31.3.135.232", // OpenNIC (Switzerland)
"80.67.169.40", // FDN (France)
"209.58.179.186", // Cyberghost (Singapore)
"89.233.43.71", // http://censurfridns.dk (Denmark)
"109.69.8.51", // punCAT (Spain)
"193.58.251.251", // SkyDNS (Russia)
};

static boost::mutex instance_lock;
Expand Down Expand Up @@ -97,11 +98,16 @@ get_builtin_cert(void)
*/

/** return the built in root DS trust anchor */
static const char*
static const char* const*
get_builtin_ds(void)
{
return
". IN DS 19036 8 2 49AAC11D7B6F6446702E54A1607371607A1A41855200FD2CE1CDDE32F24E8FB5\n";
static const char * const ds[] =
{
". IN DS 19036 8 2 49AAC11D7B6F6446702E54A1607371607A1A41855200FD2CE1CDDE32F24E8FB5\n",
". IN DS 20326 8 2 E06D44B80B8F1D39A95C0B0D7C65D08458E880409BBC683457104237C7F8EC8D\n",
NULL
};
return ds;
}

/************************************************************
Expand All @@ -113,10 +119,25 @@ get_builtin_ds(void)
namespace tools
{

static const char *get_record_name(int record_type)
{
switch (record_type)
{
case DNS_TYPE_A: return "A";
case DNS_TYPE_TXT: return "TXT";
case DNS_TYPE_AAAA: return "AAAA";
default: return "unknown";
}
}

// fuck it, I'm tired of dealing with getnameinfo()/inet_ntop/etc
std::string ipv4_to_string(const char* src, size_t len)
boost::optional<std::string> ipv4_to_string(const char* src, size_t len)
{
assert(len >= 4);
if (len < 4)
{
MERROR("Invalid IPv4 address: " << std::string(src, len));
return boost::none;
}

std::stringstream ss;
unsigned int bytes[4];
Expand All @@ -134,9 +155,13 @@ std::string ipv4_to_string(const char* src, size_t len)

// this obviously will need to change, but is here to reflect the above
// stop-gap measure and to make the tests pass at least...
std::string ipv6_to_string(const char* src, size_t len)
boost::optional<std::string> ipv6_to_string(const char* src, size_t len)
{
assert(len >= 8);
if (len < 8)
{
MERROR("Invalid IPv4 address: " << std::string(src, len));
return boost::none;
}

std::stringstream ss;
unsigned int bytes[8];
Expand All @@ -156,8 +181,10 @@ std::string ipv6_to_string(const char* src, size_t len)
return ss.str();
}

std::string txt_to_string(const char* src, size_t len)
boost::optional<std::string> txt_to_string(const char* src, size_t len)
{
if (len == 0)
return boost::none;
return std::string(src+1, len-1);
}

Expand Down Expand Up @@ -206,13 +233,24 @@ class string_copy {
char *str;
};

static void add_anchors(ub_ctx *ctx)
{
const char * const *ds = ::get_builtin_ds();
while (*ds)
{
MINFO("adding trust anchor: " << *ds);
ub_ctx_add_ta(ctx, string_copy(*ds++));
}
}

DNSResolver::DNSResolver() : m_data(new DNSResolverData())
{
int use_dns_public = 0;
std::vector<std::string> dns_public_addr;
if (auto res = getenv("DNS_PUBLIC"))
const char *DNS_PUBLIC = getenv("DNS_PUBLIC");
if (DNS_PUBLIC)
{
dns_public_addr = tools::dns_utils::parse_dns_public(res);
dns_public_addr = tools::dns_utils::parse_dns_public(DNS_PUBLIC);
if (!dns_public_addr.empty())
{
MGINFO("Using public DNS server(s): " << boost::join(dns_public_addr, ", ") << " (TCP)");
Expand Down Expand Up @@ -240,7 +278,28 @@ DNSResolver::DNSResolver() : m_data(new DNSResolverData())
ub_ctx_hosts(m_data->m_ub_context, NULL);
}

ub_ctx_add_ta(m_data->m_ub_context, string_copy(::get_builtin_ds()));
add_anchors(m_data->m_ub_context);

if (!DNS_PUBLIC)
{
// if no DNS_PUBLIC specified, we try a lookup to what we know
// should be a valid DNSSEC record, and switch to known good
// DNSSEC resolvers if verification fails
bool available, valid;
static const char *probe_hostname = "updates.moneropulse.org";
auto records = get_txt_record(probe_hostname, available, valid);
if (!valid)
{
MINFO("Failed to verify DNSSEC record from " << probe_hostname << ", falling back to TCP with well known DNSSEC resolvers");
ub_ctx_delete(m_data->m_ub_context);
m_data->m_ub_context = ub_ctx_create();
add_anchors(m_data->m_ub_context);
for (const auto &ip: DEFAULT_DNS_PUBLIC_ADDR)
ub_ctx_set_fwd(m_data->m_ub_context, string_copy(ip));
ub_ctx_set_option(m_data->m_ub_context, string_copy("do-udp:"), string_copy("no"));
ub_ctx_set_option(m_data->m_ub_context, string_copy("do-tcp:"), string_copy("yes"));
}
}
}

DNSResolver::~DNSResolver()
Expand All @@ -255,7 +314,7 @@ DNSResolver::~DNSResolver()
}
}

std::vector<std::string> DNSResolver::get_record(const std::string& url, int record_type, std::string (*reader)(const char *,size_t), bool& dnssec_available, bool& dnssec_valid)
std::vector<std::string> DNSResolver::get_record(const std::string& url, int record_type, boost::optional<std::string> (*reader)(const char *,size_t), bool& dnssec_available, bool& dnssec_valid)
{
std::vector<std::string> addresses;
dnssec_available = false;
Expand All @@ -278,7 +337,12 @@ std::vector<std::string> DNSResolver::get_record(const std::string& url, int rec
{
for (size_t i=0; result->data[i] != NULL; i++)
{
addresses.push_back((*reader)(result->data[i], result->len[i]));
boost::optional<std::string> res = (*reader)(result->data[i], result->len[i]);
if (res)
{
MINFO("Found \"" << *res << "\" in " << get_record_name(record_type) << " record for " << url);
addresses.push_back(*res);
}
}
}
}
Expand Down Expand Up @@ -475,12 +539,12 @@ bool load_txt_records_from_dns(std::vector<std::string> &good_records, const std
if (!avail[cur_index])
{
records[cur_index].clear();
LOG_PRINT_L2("DNSSEC not available for checkpoint update at URL: " << url << ", skipping.");
LOG_PRINT_L2("DNSSEC not available for hostname: " << url << ", skipping.");
}
if (!valid[cur_index])
{
records[cur_index].clear();
LOG_PRINT_L2("DNSSEC validation failed for checkpoint update at URL: " << url << ", skipping.");
LOG_PRINT_L2("DNSSEC validation failed for hostname: " << url << ", skipping.");
}

cur_index++;
Expand All @@ -502,7 +566,7 @@ bool load_txt_records_from_dns(std::vector<std::string> &good_records, const std

if (num_valid_records < 2)
{
LOG_PRINT_L0("WARNING: no two valid MoneroPulse DNS checkpoint records were received");
LOG_PRINT_L0("WARNING: no two valid DNS TXT records were received");
return false;
}

Expand All @@ -524,7 +588,7 @@ bool load_txt_records_from_dns(std::vector<std::string> &good_records, const std

if (good_records_index < 0)
{
LOG_PRINT_L0("WARNING: no two MoneroPulse DNS checkpoint records matched");
LOG_PRINT_L0("WARNING: no two DNS TXT records matched");
return false;
}

Expand Down
3 changes: 2 additions & 1 deletion src/common/dns_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include <vector>
#include <string>
#include <functional>
#include <boost/optional/optional_fwd.hpp>

namespace tools
{
Expand Down Expand Up @@ -143,7 +144,7 @@ class DNSResolver
* @return A vector of strings containing the requested record; or an empty vector
*/
// TODO: modify this to accommodate DNSSEC
std::vector<std::string> get_record(const std::string& url, int record_type, std::string (*reader)(const char *,size_t), bool& dnssec_available, bool& dnssec_valid);
std::vector<std::string> get_record(const std::string& url, int record_type, boost::optional<std::string> (*reader)(const char *,size_t), bool& dnssec_available, bool& dnssec_valid);

/**
* @brief Checks a string to see if it looks like a URL
Expand Down
2 changes: 1 addition & 1 deletion tests/unit_tests/address_from_url.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ TEST(AddressFromURL, Failure)
{
bool dnssec_result = false;

std::vector<std::string> addresses = tools::dns_utils::addresses_from_url("example.invalid", dnssec_result);
std::vector<std::string> addresses = tools::dns_utils::addresses_from_url("example.veryinvalid", dnssec_result);

// for a non-existing domain such as "example.invalid", the non-existence is proved with NSEC records
ASSERT_TRUE(dnssec_result);
Expand Down

0 comments on commit c3763a1

Please sign in to comment.