// SPDX-FileCopyrightText: Matteo Settenvini // SPDX-License-Identifier: GPL-3.0-or-later #include "testsuite.hh" #include "resolver.hh" #include #include #include #include #include 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(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(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(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(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