Branch data Line data Source code
1 : : /* SPDX-License-Identifier: LGPL-2.1+ */
2 : :
3 : : #include <netinet/ip.h>
4 : :
5 : : #include "sd-bus.h"
6 : :
7 : : #include "af-list.h"
8 : : #include "alloc-util.h"
9 : : #include "bus-common-errors.h"
10 : : #include "dns-type.h"
11 : : #include "random-util.h"
12 : : #include "resolved-def.h"
13 : : #include "string-util.h"
14 : : #include "time-util.h"
15 : :
16 : 0 : static void prefix_random(const char *name, char **ret) {
17 : : uint64_t i, u;
18 : 0 : char *m = NULL;
19 : :
20 : 0 : u = 1 + (random_u64() & 3);
21 : :
22 [ # # ]: 0 : for (i = 0; i < u; i++) {
23 : 0 : _cleanup_free_ char *b = NULL;
24 : : char *x;
25 : :
26 [ # # ]: 0 : assert_se(asprintf(&b, "x%" PRIu64 "x", random_u64()));
27 : 0 : x = strjoin(b, ".", name);
28 [ # # ]: 0 : assert_se(x);
29 : :
30 : 0 : free(m);
31 : 0 : m = x;
32 : : }
33 : :
34 : 0 : *ret = m;
35 : 0 : }
36 : :
37 : 0 : static void test_rr_lookup(sd_bus *bus, const char *name, uint16_t type, const char *result) {
38 : 0 : _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL;
39 : 0 : _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
40 : 0 : _cleanup_free_ char *m = NULL;
41 : : int r;
42 : :
43 : : /* If the name starts with a dot, we prefix one to three random labels */
44 [ # # ]: 0 : if (startswith(name, ".")) {
45 : 0 : prefix_random(name + 1, &m);
46 : 0 : name = m;
47 : : }
48 : :
49 [ # # ]: 0 : assert_se(sd_bus_message_new_method_call(
50 : : bus,
51 : : &req,
52 : : "org.freedesktop.resolve1",
53 : : "/org/freedesktop/resolve1",
54 : : "org.freedesktop.resolve1.Manager",
55 : : "ResolveRecord") >= 0);
56 : :
57 [ # # ]: 0 : assert_se(sd_bus_message_append(req, "isqqt", 0, name, DNS_CLASS_IN, type, UINT64_C(0)) >= 0);
58 : :
59 : 0 : r = sd_bus_call(bus, req, SD_RESOLVED_QUERY_TIMEOUT_USEC, &error, &reply);
60 : :
61 [ # # ]: 0 : if (r < 0) {
62 [ # # ]: 0 : assert_se(result);
63 [ # # ]: 0 : assert_se(sd_bus_error_has_name(&error, result));
64 [ # # ]: 0 : log_info("[OK] %s/%s resulted in <%s>.", name, dns_type_to_string(type), error.name);
65 : : } else {
66 [ # # ]: 0 : assert_se(!result);
67 [ # # ]: 0 : log_info("[OK] %s/%s succeeded.", name, dns_type_to_string(type));
68 : : }
69 : 0 : }
70 : :
71 : 0 : static void test_hostname_lookup(sd_bus *bus, const char *name, int family, const char *result) {
72 : 0 : _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL;
73 : 0 : _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
74 : 0 : _cleanup_free_ char *m = NULL;
75 : : const char *af;
76 : : int r;
77 : :
78 [ # # ]: 0 : af = family == AF_UNSPEC ? "AF_UNSPEC" : af_to_name(family);
79 : :
80 : : /* If the name starts with a dot, we prefix one to three random labels */
81 [ # # ]: 0 : if (startswith(name, ".")) {
82 : 0 : prefix_random(name + 1, &m);
83 : 0 : name = m;
84 : : }
85 : :
86 [ # # ]: 0 : assert_se(sd_bus_message_new_method_call(
87 : : bus,
88 : : &req,
89 : : "org.freedesktop.resolve1",
90 : : "/org/freedesktop/resolve1",
91 : : "org.freedesktop.resolve1.Manager",
92 : : "ResolveHostname") >= 0);
93 : :
94 [ # # ]: 0 : assert_se(sd_bus_message_append(req, "isit", 0, name, family, UINT64_C(0)) >= 0);
95 : :
96 : 0 : r = sd_bus_call(bus, req, SD_RESOLVED_QUERY_TIMEOUT_USEC, &error, &reply);
97 : :
98 [ # # ]: 0 : if (r < 0) {
99 [ # # ]: 0 : assert_se(result);
100 [ # # ]: 0 : assert_se(sd_bus_error_has_name(&error, result));
101 [ # # ]: 0 : log_info("[OK] %s/%s resulted in <%s>.", name, af, error.name);
102 : : } else {
103 [ # # ]: 0 : assert_se(!result);
104 [ # # ]: 0 : log_info("[OK] %s/%s succeeded.", name, af);
105 : : }
106 : :
107 : 0 : }
108 : :
109 : 0 : int main(int argc, char* argv[]) {
110 : 0 : _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
111 : :
112 : : /* Note that this is a manual test as it requires:
113 : : *
114 : : * Full network access
115 : : * A DNSSEC capable DNS server
116 : : * That zones contacted are still set up as they were when I wrote this.
117 : : */
118 : :
119 [ # # ]: 0 : assert_se(sd_bus_open_system(&bus) >= 0);
120 : :
121 : : /* Normally signed */
122 : 0 : test_rr_lookup(bus, "www.eurid.eu", DNS_TYPE_A, NULL);
123 : 0 : test_hostname_lookup(bus, "www.eurid.eu", AF_UNSPEC, NULL);
124 : :
125 : 0 : test_rr_lookup(bus, "sigok.verteiltesysteme.net", DNS_TYPE_A, NULL);
126 : 0 : test_hostname_lookup(bus, "sigok.verteiltesysteme.net", AF_UNSPEC, NULL);
127 : :
128 : : /* Normally signed, NODATA */
129 : 0 : test_rr_lookup(bus, "www.eurid.eu", DNS_TYPE_RP, BUS_ERROR_NO_SUCH_RR);
130 : 0 : test_rr_lookup(bus, "sigok.verteiltesysteme.net", DNS_TYPE_RP, BUS_ERROR_NO_SUCH_RR);
131 : :
132 : : /* Invalid signature */
133 : 0 : test_rr_lookup(bus, "sigfail.verteiltesysteme.net", DNS_TYPE_A, BUS_ERROR_DNSSEC_FAILED);
134 : 0 : test_hostname_lookup(bus, "sigfail.verteiltesysteme.net", AF_INET, BUS_ERROR_DNSSEC_FAILED);
135 : :
136 : : /* Invalid signature, RSA, wildcard */
137 : 0 : test_rr_lookup(bus, ".wilda.rhybar.0skar.cz", DNS_TYPE_A, BUS_ERROR_DNSSEC_FAILED);
138 : 0 : test_hostname_lookup(bus, ".wilda.rhybar.0skar.cz", AF_INET, BUS_ERROR_DNSSEC_FAILED);
139 : :
140 : : /* Invalid signature, ECDSA, wildcard */
141 : 0 : test_rr_lookup(bus, ".wilda.rhybar.ecdsa.0skar.cz", DNS_TYPE_A, BUS_ERROR_DNSSEC_FAILED);
142 : 0 : test_hostname_lookup(bus, ".wilda.rhybar.ecdsa.0skar.cz", AF_INET, BUS_ERROR_DNSSEC_FAILED);
143 : :
144 : : /* Missing DS for DNSKEY */
145 : 0 : test_rr_lookup(bus, "www.dnssec-bogus.sg", DNS_TYPE_A, BUS_ERROR_DNSSEC_FAILED);
146 : 0 : test_hostname_lookup(bus, "www.dnssec-bogus.sg", AF_INET, BUS_ERROR_DNSSEC_FAILED);
147 : :
148 : : /* NXDOMAIN in NSEC domain */
149 : 0 : test_rr_lookup(bus, "hhh.nasa.gov", DNS_TYPE_A, _BUS_ERROR_DNS "NXDOMAIN");
150 : 0 : test_hostname_lookup(bus, "hhh.nasa.gov", AF_UNSPEC, _BUS_ERROR_DNS "NXDOMAIN");
151 : 0 : test_rr_lookup(bus, "_pgpkey-https._tcp.hkps.pool.sks-keyservers.net", DNS_TYPE_SRV, _BUS_ERROR_DNS "NXDOMAIN");
152 : :
153 : : /* wildcard, NSEC zone */
154 : 0 : test_rr_lookup(bus, ".wilda.nsec.0skar.cz", DNS_TYPE_A, NULL);
155 : 0 : test_hostname_lookup(bus, ".wilda.nsec.0skar.cz", AF_INET, NULL);
156 : :
157 : : /* wildcard, NSEC zone, NODATA */
158 : 0 : test_rr_lookup(bus, ".wilda.nsec.0skar.cz", DNS_TYPE_RP, BUS_ERROR_NO_SUCH_RR);
159 : :
160 : : /* wildcard, NSEC3 zone */
161 : 0 : test_rr_lookup(bus, ".wilda.0skar.cz", DNS_TYPE_A, NULL);
162 : 0 : test_hostname_lookup(bus, ".wilda.0skar.cz", AF_INET, NULL);
163 : :
164 : : /* wildcard, NSEC3 zone, NODATA */
165 : 0 : test_rr_lookup(bus, ".wilda.0skar.cz", DNS_TYPE_RP, BUS_ERROR_NO_SUCH_RR);
166 : :
167 : : /* wildcard, NSEC zone, CNAME */
168 : 0 : test_rr_lookup(bus, ".wild.nsec.0skar.cz", DNS_TYPE_A, NULL);
169 : 0 : test_hostname_lookup(bus, ".wild.nsec.0skar.cz", AF_UNSPEC, NULL);
170 : 0 : test_hostname_lookup(bus, ".wild.nsec.0skar.cz", AF_INET, NULL);
171 : :
172 : : /* wildcard, NSEC zone, NODATA, CNAME */
173 : 0 : test_rr_lookup(bus, ".wild.nsec.0skar.cz", DNS_TYPE_RP, BUS_ERROR_NO_SUCH_RR);
174 : :
175 : : /* wildcard, NSEC3 zone, CNAME */
176 : 0 : test_rr_lookup(bus, ".wild.0skar.cz", DNS_TYPE_A, NULL);
177 : 0 : test_hostname_lookup(bus, ".wild.0skar.cz", AF_UNSPEC, NULL);
178 : 0 : test_hostname_lookup(bus, ".wild.0skar.cz", AF_INET, NULL);
179 : :
180 : : /* wildcard, NSEC3 zone, NODATA, CNAME */
181 : 0 : test_rr_lookup(bus, ".wild.0skar.cz", DNS_TYPE_RP, BUS_ERROR_NO_SUCH_RR);
182 : :
183 : : /* NODATA due to empty non-terminal in NSEC domain */
184 : 0 : test_rr_lookup(bus, "herndon.nasa.gov", DNS_TYPE_A, BUS_ERROR_NO_SUCH_RR);
185 : 0 : test_hostname_lookup(bus, "herndon.nasa.gov", AF_UNSPEC, BUS_ERROR_NO_SUCH_RR);
186 : 0 : test_hostname_lookup(bus, "herndon.nasa.gov", AF_INET, BUS_ERROR_NO_SUCH_RR);
187 : 0 : test_hostname_lookup(bus, "herndon.nasa.gov", AF_INET6, BUS_ERROR_NO_SUCH_RR);
188 : :
189 : : /* NXDOMAIN in NSEC root zone: */
190 : 0 : test_rr_lookup(bus, "jasdhjas.kjkfgjhfjg", DNS_TYPE_A, _BUS_ERROR_DNS "NXDOMAIN");
191 : 0 : test_hostname_lookup(bus, "jasdhjas.kjkfgjhfjg", AF_UNSPEC, _BUS_ERROR_DNS "NXDOMAIN");
192 : 0 : test_hostname_lookup(bus, "jasdhjas.kjkfgjhfjg", AF_INET, _BUS_ERROR_DNS "NXDOMAIN");
193 : 0 : test_hostname_lookup(bus, "jasdhjas.kjkfgjhfjg", AF_INET6, _BUS_ERROR_DNS "NXDOMAIN");
194 : :
195 : : /* NXDOMAIN in NSEC3 .com zone: */
196 : 0 : test_rr_lookup(bus, "kjkfgjhfjgsdfdsfd.com", DNS_TYPE_A, _BUS_ERROR_DNS "NXDOMAIN");
197 : 0 : test_hostname_lookup(bus, "kjkfgjhfjgsdfdsfd.com", AF_INET, _BUS_ERROR_DNS "NXDOMAIN");
198 : 0 : test_hostname_lookup(bus, "kjkfgjhfjgsdfdsfd.com", AF_INET6, _BUS_ERROR_DNS "NXDOMAIN");
199 : 0 : test_hostname_lookup(bus, "kjkfgjhfjgsdfdsfd.com", AF_UNSPEC, _BUS_ERROR_DNS "NXDOMAIN");
200 : :
201 : : /* Unsigned A */
202 : 0 : test_rr_lookup(bus, "poettering.de", DNS_TYPE_A, NULL);
203 : 0 : test_rr_lookup(bus, "poettering.de", DNS_TYPE_AAAA, NULL);
204 : 0 : test_hostname_lookup(bus, "poettering.de", AF_UNSPEC, NULL);
205 : 0 : test_hostname_lookup(bus, "poettering.de", AF_INET, NULL);
206 : 0 : test_hostname_lookup(bus, "poettering.de", AF_INET6, NULL);
207 : :
208 : : #if HAVE_LIBIDN2 || HAVE_LIBIDN
209 : : /* Unsigned A with IDNA conversion necessary */
210 : 0 : test_hostname_lookup(bus, "pöttering.de", AF_UNSPEC, NULL);
211 : 0 : test_hostname_lookup(bus, "pöttering.de", AF_INET, NULL);
212 : 0 : test_hostname_lookup(bus, "pöttering.de", AF_INET6, NULL);
213 : : #endif
214 : :
215 : : /* DNAME, pointing to NXDOMAIN */
216 : 0 : test_rr_lookup(bus, ".ireallyhpoethisdoesnexist.xn--kprw13d.", DNS_TYPE_A, _BUS_ERROR_DNS "NXDOMAIN");
217 : 0 : test_rr_lookup(bus, ".ireallyhpoethisdoesnexist.xn--kprw13d.", DNS_TYPE_RP, _BUS_ERROR_DNS "NXDOMAIN");
218 : 0 : test_hostname_lookup(bus, ".ireallyhpoethisdoesntexist.xn--kprw13d.", AF_UNSPEC, _BUS_ERROR_DNS "NXDOMAIN");
219 : 0 : test_hostname_lookup(bus, ".ireallyhpoethisdoesntexist.xn--kprw13d.", AF_INET, _BUS_ERROR_DNS "NXDOMAIN");
220 : 0 : test_hostname_lookup(bus, ".ireallyhpoethisdoesntexist.xn--kprw13d.", AF_INET6, _BUS_ERROR_DNS "NXDOMAIN");
221 : :
222 : 0 : return 0;
223 : : }
|