]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/resolve/test-dnssec-complex.c
Add SPDX license identifiers to source files under the LGPL
[thirdparty/systemd.git] / src / resolve / test-dnssec-complex.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2 /***
3 This file is part of systemd.
4
5 Copyright 2016 Lennart Poettering
6
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
11
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
19 ***/
20
21 #include <netinet/ip.h>
22
23 #include "sd-bus.h"
24
25 #include "af-list.h"
26 #include "alloc-util.h"
27 #include "bus-common-errors.h"
28 #include "dns-type.h"
29 #include "random-util.h"
30 #include "string-util.h"
31 #include "time-util.h"
32
33 #define DNS_CALL_TIMEOUT_USEC (45*USEC_PER_SEC)
34
35 static void prefix_random(const char *name, char **ret) {
36 uint64_t i, u;
37 char *m = NULL;
38
39 u = 1 + (random_u64() & 3);
40
41 for (i = 0; i < u; i++) {
42 _cleanup_free_ char *b = NULL;
43 char *x;
44
45 assert_se(asprintf(&b, "x%" PRIu64 "x", random_u64()));
46 x = strjoin(b, ".", name);
47 assert_se(x);
48
49 free(m);
50 m = x;
51 }
52
53 *ret = m;
54 }
55
56 static void test_rr_lookup(sd_bus *bus, const char *name, uint16_t type, const char *result) {
57 _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL;
58 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
59 _cleanup_free_ char *m = NULL;
60 int r;
61
62 /* If the name starts with a dot, we prefix one to three random labels */
63 if (startswith(name, ".")) {
64 prefix_random(name + 1, &m);
65 name = m;
66 }
67
68 assert_se(sd_bus_message_new_method_call(
69 bus,
70 &req,
71 "org.freedesktop.resolve1",
72 "/org/freedesktop/resolve1",
73 "org.freedesktop.resolve1.Manager",
74 "ResolveRecord") >= 0);
75
76 assert_se(sd_bus_message_append(req, "isqqt", 0, name, DNS_CLASS_IN, type, UINT64_C(0)) >= 0);
77
78 r = sd_bus_call(bus, req, DNS_CALL_TIMEOUT_USEC, &error, &reply);
79
80 if (r < 0) {
81 assert_se(result);
82 assert_se(sd_bus_error_has_name(&error, result));
83 log_info("[OK] %s/%s resulted in <%s>.", name, dns_type_to_string(type), error.name);
84 } else {
85 assert_se(!result);
86 log_info("[OK] %s/%s succeeded.", name, dns_type_to_string(type));
87 }
88 }
89
90 static void test_hostname_lookup(sd_bus *bus, const char *name, int family, const char *result) {
91 _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL;
92 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
93 _cleanup_free_ char *m = NULL;
94 const char *af;
95 int r;
96
97 af = family == AF_UNSPEC ? "AF_UNSPEC" : af_to_name(family);
98
99 /* If the name starts with a dot, we prefix one to three random labels */
100 if (startswith(name, ".")) {
101 prefix_random(name + 1, &m);
102 name = m;
103 }
104
105 assert_se(sd_bus_message_new_method_call(
106 bus,
107 &req,
108 "org.freedesktop.resolve1",
109 "/org/freedesktop/resolve1",
110 "org.freedesktop.resolve1.Manager",
111 "ResolveHostname") >= 0);
112
113 assert_se(sd_bus_message_append(req, "isit", 0, name, family, UINT64_C(0)) >= 0);
114
115 r = sd_bus_call(bus, req, DNS_CALL_TIMEOUT_USEC, &error, &reply);
116
117 if (r < 0) {
118 assert_se(result);
119 assert_se(sd_bus_error_has_name(&error, result));
120 log_info("[OK] %s/%s resulted in <%s>.", name, af, error.name);
121 } else {
122 assert_se(!result);
123 log_info("[OK] %s/%s succeeded.", name, af);
124 }
125
126 }
127
128 int main(int argc, char* argv[]) {
129 _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
130
131 /* Note that this is a manual test as it requires:
132 *
133 * Full network access
134 * A DNSSEC capable DNS server
135 * That zones contacted are still set up as they were when I wrote this.
136 */
137
138 assert_se(sd_bus_open_system(&bus) >= 0);
139
140 /* Normally signed */
141 test_rr_lookup(bus, "www.eurid.eu", DNS_TYPE_A, NULL);
142 test_hostname_lookup(bus, "www.eurid.eu", AF_UNSPEC, NULL);
143
144 test_rr_lookup(bus, "sigok.verteiltesysteme.net", DNS_TYPE_A, NULL);
145 test_hostname_lookup(bus, "sigok.verteiltesysteme.net", AF_UNSPEC, NULL);
146
147 /* Normally signed, NODATA */
148 test_rr_lookup(bus, "www.eurid.eu", DNS_TYPE_RP, BUS_ERROR_NO_SUCH_RR);
149 test_rr_lookup(bus, "sigok.verteiltesysteme.net", DNS_TYPE_RP, BUS_ERROR_NO_SUCH_RR);
150
151 /* Invalid signature */
152 test_rr_lookup(bus, "sigfail.verteiltesysteme.net", DNS_TYPE_A, BUS_ERROR_DNSSEC_FAILED);
153 test_hostname_lookup(bus, "sigfail.verteiltesysteme.net", AF_INET, BUS_ERROR_DNSSEC_FAILED);
154
155 /* Invalid signature, RSA, wildcard */
156 test_rr_lookup(bus, ".wilda.rhybar.0skar.cz", DNS_TYPE_A, BUS_ERROR_DNSSEC_FAILED);
157 test_hostname_lookup(bus, ".wilda.rhybar.0skar.cz", AF_INET, BUS_ERROR_DNSSEC_FAILED);
158
159 /* Invalid signature, ECDSA, wildcard */
160 test_rr_lookup(bus, ".wilda.rhybar.ecdsa.0skar.cz", DNS_TYPE_A, BUS_ERROR_DNSSEC_FAILED);
161 test_hostname_lookup(bus, ".wilda.rhybar.ecdsa.0skar.cz", AF_INET, BUS_ERROR_DNSSEC_FAILED);
162
163 /* NXDOMAIN in NSEC domain */
164 test_rr_lookup(bus, "hhh.nasa.gov", DNS_TYPE_A, _BUS_ERROR_DNS "NXDOMAIN");
165 test_hostname_lookup(bus, "hhh.nasa.gov", AF_UNSPEC, _BUS_ERROR_DNS "NXDOMAIN");
166
167 /* wildcard, NSEC zone */
168 test_rr_lookup(bus, ".wilda.nsec.0skar.cz", DNS_TYPE_A, NULL);
169 test_hostname_lookup(bus, ".wilda.nsec.0skar.cz", AF_INET, NULL);
170
171 /* wildcard, NSEC zone, NODATA */
172 test_rr_lookup(bus, ".wilda.nsec.0skar.cz", DNS_TYPE_RP, BUS_ERROR_NO_SUCH_RR);
173
174 /* wildcard, NSEC3 zone */
175 test_rr_lookup(bus, ".wilda.0skar.cz", DNS_TYPE_A, NULL);
176 test_hostname_lookup(bus, ".wilda.0skar.cz", AF_INET, NULL);
177
178 /* wildcard, NSEC3 zone, NODATA */
179 test_rr_lookup(bus, ".wilda.0skar.cz", DNS_TYPE_RP, BUS_ERROR_NO_SUCH_RR);
180
181 /* wildcard, NSEC zone, CNAME */
182 test_rr_lookup(bus, ".wild.nsec.0skar.cz", DNS_TYPE_A, NULL);
183 test_hostname_lookup(bus, ".wild.nsec.0skar.cz", AF_UNSPEC, NULL);
184 test_hostname_lookup(bus, ".wild.nsec.0skar.cz", AF_INET, NULL);
185
186 /* wildcard, NSEC zone, NODATA, CNAME */
187 test_rr_lookup(bus, ".wild.nsec.0skar.cz", DNS_TYPE_RP, BUS_ERROR_NO_SUCH_RR);
188
189 /* wildcard, NSEC3 zone, CNAME */
190 test_rr_lookup(bus, ".wild.0skar.cz", DNS_TYPE_A, NULL);
191 test_hostname_lookup(bus, ".wild.0skar.cz", AF_UNSPEC, NULL);
192 test_hostname_lookup(bus, ".wild.0skar.cz", AF_INET, NULL);
193
194 /* wildcard, NSEC3 zone, NODATA, CNAME */
195 test_rr_lookup(bus, ".wild.0skar.cz", DNS_TYPE_RP, BUS_ERROR_NO_SUCH_RR);
196
197 /* NODATA due to empty non-terminal in NSEC domain */
198 test_rr_lookup(bus, "herndon.nasa.gov", DNS_TYPE_A, BUS_ERROR_NO_SUCH_RR);
199 test_hostname_lookup(bus, "herndon.nasa.gov", AF_UNSPEC, BUS_ERROR_NO_SUCH_RR);
200 test_hostname_lookup(bus, "herndon.nasa.gov", AF_INET, BUS_ERROR_NO_SUCH_RR);
201 test_hostname_lookup(bus, "herndon.nasa.gov", AF_INET6, BUS_ERROR_NO_SUCH_RR);
202
203 /* NXDOMAIN in NSEC root zone: */
204 test_rr_lookup(bus, "jasdhjas.kjkfgjhfjg", DNS_TYPE_A, _BUS_ERROR_DNS "NXDOMAIN");
205 test_hostname_lookup(bus, "jasdhjas.kjkfgjhfjg", AF_UNSPEC, _BUS_ERROR_DNS "NXDOMAIN");
206 test_hostname_lookup(bus, "jasdhjas.kjkfgjhfjg", AF_INET, _BUS_ERROR_DNS "NXDOMAIN");
207 test_hostname_lookup(bus, "jasdhjas.kjkfgjhfjg", AF_INET6, _BUS_ERROR_DNS "NXDOMAIN");
208
209 /* NXDOMAIN in NSEC3 .com zone: */
210 test_rr_lookup(bus, "kjkfgjhfjgsdfdsfd.com", DNS_TYPE_A, _BUS_ERROR_DNS "NXDOMAIN");
211 test_hostname_lookup(bus, "kjkfgjhfjgsdfdsfd.com", AF_INET, _BUS_ERROR_DNS "NXDOMAIN");
212 test_hostname_lookup(bus, "kjkfgjhfjgsdfdsfd.com", AF_INET6, _BUS_ERROR_DNS "NXDOMAIN");
213 test_hostname_lookup(bus, "kjkfgjhfjgsdfdsfd.com", AF_UNSPEC, _BUS_ERROR_DNS "NXDOMAIN");
214
215 /* Unsigned A */
216 test_rr_lookup(bus, "poettering.de", DNS_TYPE_A, NULL);
217 test_rr_lookup(bus, "poettering.de", DNS_TYPE_AAAA, NULL);
218 test_hostname_lookup(bus, "poettering.de", AF_UNSPEC, NULL);
219 test_hostname_lookup(bus, "poettering.de", AF_INET, NULL);
220 test_hostname_lookup(bus, "poettering.de", AF_INET6, NULL);
221
222 #if HAVE_LIBIDN2 || HAVE_LIBIDN
223 /* Unsigned A with IDNA conversion necessary */
224 test_hostname_lookup(bus, "pöttering.de", AF_UNSPEC, NULL);
225 test_hostname_lookup(bus, "pöttering.de", AF_INET, NULL);
226 test_hostname_lookup(bus, "pöttering.de", AF_INET6, NULL);
227 #endif
228
229 /* DNAME, pointing to NXDOMAIN */
230 test_rr_lookup(bus, ".ireallyhpoethisdoesnexist.xn--kprw13d.", DNS_TYPE_A, _BUS_ERROR_DNS "NXDOMAIN");
231 test_rr_lookup(bus, ".ireallyhpoethisdoesnexist.xn--kprw13d.", DNS_TYPE_RP, _BUS_ERROR_DNS "NXDOMAIN");
232 test_hostname_lookup(bus, ".ireallyhpoethisdoesntexist.xn--kprw13d.", AF_UNSPEC, _BUS_ERROR_DNS "NXDOMAIN");
233 test_hostname_lookup(bus, ".ireallyhpoethisdoesntexist.xn--kprw13d.", AF_INET, _BUS_ERROR_DNS "NXDOMAIN");
234 test_hostname_lookup(bus, ".ireallyhpoethisdoesntexist.xn--kprw13d.", AF_INET6, _BUS_ERROR_DNS "NXDOMAIN");
235
236 return 0;
237 }