193 lines
6.0 KiB
C++
193 lines
6.0 KiB
C++
// SPDX-FileCopyrightText: Matteo Settenvini <matteo.settenvini@montecristosoftware.eu>
|
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
#include "testsuite.hh"
|
|
|
|
#include "resolver.hh"
|
|
|
|
#include <glib.h>
|
|
|
|
#include <array>
|
|
#include <format>
|
|
#include <netdb.h>
|
|
#include <sys/socket.h>
|
|
|
|
namespace /* anonymous */ {
|
|
|
|
auto resolver_valid_dns_address(gconstpointer addr_cstr) -> void;
|
|
auto resolver_invalid_dns_address(gconstpointer addr_cstr) -> void;
|
|
auto resolver_dns0eu_blocks_unsafe_domains(gconstpointer should_be_blocked_cstr) -> void;
|
|
auto resolver_cloudflare_family_blocks_unsafe_domains(gconstpointer should_be_blocked_cstr) -> void;
|
|
|
|
} // ~ namespace anonymous
|
|
|
|
auto define_resolver_tests() -> void {
|
|
auto valid_dns_addrs = std::array {
|
|
"192.168.0.1",
|
|
"192.168.0.1:53",
|
|
"192.168.0.1#dns.example.com",
|
|
"192.168.0.1:53#dns.example.com",
|
|
"192.168.0.1#",
|
|
"2345:0425:2ca1:0000:0000:0567:5673:23b5",
|
|
"2345:425:2ca1::567:5673:23b5",
|
|
"[2345::5673:23b5]:63",
|
|
"[2345::5673:23b5]:63#example.com",
|
|
"2345::5673:23b5#example.com",
|
|
"[2345::5673:23b5]:",
|
|
"[2345::5673:23b5]:#foo.bar",
|
|
"2345::5673:23b5#",
|
|
};
|
|
|
|
for (auto addr: valid_dns_addrs) {
|
|
g_test_add_data_func(std::format("/resolver/parses-valid-dns/{}", addr).c_str(),
|
|
addr, resolver_valid_dns_address);
|
|
}
|
|
|
|
auto invalid_dns_addrs = std::array {
|
|
"192.168.0.1.1",
|
|
"192.168.0.256",
|
|
"192.168..20",
|
|
"-192.168.0.1",
|
|
"192.168.0.1:",
|
|
"192.168.0.1:#foo.bar",
|
|
"2345:0425:2ca1:0000:0000:0567:5673:23b5:2020:2021",
|
|
"2345::5673::23b5",
|
|
"2345::5673:ghij",
|
|
"2345::5673:23b5:",
|
|
};
|
|
|
|
for (auto addr: invalid_dns_addrs) {
|
|
g_test_add_data_func(std::format("/resolver/rejects-invalid-dns/{}", addr).c_str(),
|
|
addr, resolver_invalid_dns_address);
|
|
}
|
|
|
|
// dns0.eu seems fairly good as blockfilters go
|
|
auto should_be_blocked_dns0 = std::array {
|
|
"pornhub.com",
|
|
"bookmaker.com",
|
|
"thepiratebay.org",
|
|
};
|
|
|
|
for (auto hostname : should_be_blocked_dns0) {
|
|
g_test_add_data_func(std::format("/resolver/kids.dns0.eu/blocks/{}", hostname).c_str(),
|
|
hostname, resolver_dns0eu_blocks_unsafe_domains);
|
|
}
|
|
|
|
// Cloudflare family seems far less restrictive
|
|
auto should_be_blocked_cff = std::array {
|
|
"pornhub.com",
|
|
"thepiratebay.org",
|
|
};
|
|
|
|
for (auto hostname : should_be_blocked_cff) {
|
|
g_test_add_data_func(std::format("/resolver/family.cloudflare-dns.com/blocks/{}", hostname).c_str(),
|
|
hostname, resolver_cloudflare_family_blocks_unsafe_domains);
|
|
}
|
|
}
|
|
|
|
namespace /* anonymous */ {
|
|
auto resolver_valid_dns_address(gconstpointer addr_cstr) -> void {
|
|
auto addr = static_cast<const char *>(addr_cstr);
|
|
try {
|
|
malcontent::Resolver resolver({ addr });
|
|
|
|
} catch (const std::exception& e) {
|
|
g_assert_unreachable(e.what());
|
|
}
|
|
}
|
|
|
|
auto resolver_invalid_dns_address(gconstpointer addr_cstr) -> void {
|
|
auto addr = static_cast<const char *>(addr_cstr);
|
|
try {
|
|
malcontent::Resolver resolver({ addr });
|
|
auto error = std::format("DNS addr parsing did not fail as expected for {}", addr);
|
|
g_assert_unreachable(error.c_str());
|
|
|
|
} catch (const std::invalid_argument& e) {
|
|
g_assert_true(std::string(e.what()).find("unable to parse DNS server address") != std::string::npos);
|
|
|
|
} catch (const std::exception& e) {
|
|
g_assert_unreachable(e.what());
|
|
}
|
|
}
|
|
|
|
auto resolver_dns0eu_blocks_unsafe_domains(gconstpointer should_be_blocked_cstr) -> void {
|
|
auto should_be_blocked = static_cast<const char *>(should_be_blocked_cstr);
|
|
try {
|
|
malcontent::Resolver resolver({
|
|
"193.110.81.1#kids.dns0.eu",
|
|
"2a0f:fc80::1#kids.dns0.eu",
|
|
"185.253.5.1#kids.dns0.eu",
|
|
"2a0f:fc81::1#kids.dns0.eu",
|
|
});
|
|
|
|
|
|
hostent result;
|
|
int local_errno{};
|
|
HErrno local_herrno{};
|
|
malcontent::ResolverArgs args {
|
|
.name = should_be_blocked,
|
|
.family = AF_INET,
|
|
.result = &result,
|
|
.buffer = nullptr,
|
|
.buflen = 0,
|
|
.errnop = &local_errno,
|
|
.h_errnop = &local_herrno,
|
|
.ttlp = nullptr,
|
|
};
|
|
|
|
resolver.resolve(args);
|
|
g_assert_cmpint(local_errno, ==, 0);
|
|
g_assert_true(local_herrno == HErrno::HostNotFound);
|
|
|
|
} catch (const std::exception& e) {
|
|
g_assert_unreachable(e.what());
|
|
}
|
|
}
|
|
|
|
auto resolver_cloudflare_family_blocks_unsafe_domains(gconstpointer should_be_blocked_cstr) -> void {
|
|
auto should_be_blocked = static_cast<const char *>(should_be_blocked_cstr);
|
|
|
|
const char NULL_NULL_NULL_NULL[] = { 0x0, 0x0, 0x0, 0x0 };
|
|
try {
|
|
malcontent::Resolver resolver({
|
|
"1.1.1.3#family.cloudflare-dns.com",
|
|
"1.0.0.3#family.cloudflare-dns.com",
|
|
"2606:4700:4700::1113#family.cloudflare-dns.com",
|
|
"2606:4700:4700::1003#family.cloudflare-dns.com",
|
|
});
|
|
|
|
constexpr size_t BUFLEN = 2056;
|
|
char buffer[BUFLEN];
|
|
hostent result;
|
|
int local_errno{};
|
|
HErrno local_herrno{};
|
|
malcontent::ResolverArgs args {
|
|
.name = should_be_blocked,
|
|
.family = AF_INET,
|
|
.result = &result,
|
|
.buffer = buffer,
|
|
.buflen = BUFLEN,
|
|
.errnop = &local_errno,
|
|
.h_errnop = &local_herrno,
|
|
.ttlp = nullptr,
|
|
};
|
|
|
|
resolver.resolve(args);
|
|
g_assert_cmpint(local_errno, ==, 0);
|
|
g_assert_true(local_herrno == HErrno::Success);
|
|
g_assert_cmpint(result.h_addrtype, ==, AF_INET);
|
|
g_assert_cmpint(result.h_length, ==, 4);
|
|
g_assert_nonnull(result.h_addr_list);
|
|
g_assert_cmpmem(*result.h_addr_list, result.h_length, NULL_NULL_NULL_NULL, 4);
|
|
g_assert_null(result.h_addr_list[1]);
|
|
|
|
} catch (const std::exception& e) {
|
|
g_assert_unreachable(e.what());
|
|
}
|
|
}
|
|
|
|
// TODO: TEST canary
|
|
|
|
} // ~ namespace anonymous
|