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