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