1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2016 Lennart Poettering
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.
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.
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/>.
22 #include <netinet/ip.h>
27 #include "alloc-util.h"
28 #include "bus-common-errors.h"
30 #include "random-util.h"
31 #include "string-util.h"
32 #include "time-util.h"
34 #define DNS_CALL_TIMEOUT_USEC (45*USEC_PER_SEC)
36 static void prefix_random(const char *name
, char **ret
) {
40 u
= 1 + (random_u64() & 3);
42 for (i
= 0; i
< u
; i
++) {
43 _cleanup_free_
char *b
= NULL
;
46 assert_se(asprintf(&b
, "x%" PRIu64
"x", random_u64()));
47 x
= strjoin(b
, ".", name
, NULL
);
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
;
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
);
69 assert_se(sd_bus_message_new_method_call(
72 "org.freedesktop.resolve1",
73 "/org/freedesktop/resolve1",
74 "org.freedesktop.resolve1.Manager",
75 "ResolveRecord") >= 0);
77 assert_se(sd_bus_message_append(req
, "isqqt", 0, name
, DNS_CLASS_IN
, type
, UINT64_C(0)) >= 0);
79 r
= sd_bus_call(bus
, req
, DNS_CALL_TIMEOUT_USEC
, &error
, &reply
);
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
);
87 log_info("[OK] %s/%s succeeded.", name
, dns_type_to_string(type
));
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
;
98 af
= family
== AF_UNSPEC
? "AF_UNSPEC" : af_to_name(family
);
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
);
106 assert_se(sd_bus_message_new_method_call(
109 "org.freedesktop.resolve1",
110 "/org/freedesktop/resolve1",
111 "org.freedesktop.resolve1.Manager",
112 "ResolveHostname") >= 0);
114 assert_se(sd_bus_message_append(req
, "isit", 0, name
, family
, UINT64_C(0)) >= 0);
116 r
= sd_bus_call(bus
, req
, DNS_CALL_TIMEOUT_USEC
, &error
, &reply
);
120 assert_se(sd_bus_error_has_name(&error
, result
));
121 log_info("[OK] %s/%s resulted in <%s>.", name
, af
, error
.name
);
124 log_info("[OK] %s/%s succeeded.", name
, af
);
129 int main(int argc
, char* argv
[]) {
130 _cleanup_(sd_bus_flush_close_unrefp
) sd_bus
*bus
= NULL
;
132 /* Note that this is a manual test as it requires:
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.
139 assert_se(sd_bus_open_system(&bus
) >= 0);
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
);
145 test_rr_lookup(bus
, "sigok.verteiltesysteme.net", DNS_TYPE_A
, NULL
);
146 test_hostname_lookup(bus
, "sigok.verteiltesysteme.net", AF_UNSPEC
, NULL
);
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
);
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
);
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
);
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
);
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");
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
);
172 /* wildcard, NSEC zone, NODATA */
173 test_rr_lookup(bus
, ".wilda.nsec.0skar.cz", DNS_TYPE_RP
, BUS_ERROR_NO_SUCH_RR
);
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
);
179 /* wildcard, NSEC3 zone, NODATA */
180 test_rr_lookup(bus
, ".wilda.0skar.cz", DNS_TYPE_RP
, BUS_ERROR_NO_SUCH_RR
);
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
);
187 /* wildcard, NSEC zone, NODATA, CNAME */
188 test_rr_lookup(bus
, ".wild.nsec.0skar.cz", DNS_TYPE_RP
, BUS_ERROR_NO_SUCH_RR
);
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
);
195 /* wildcard, NSEC3 zone, NODATA, CNAME */
196 test_rr_lookup(bus
, ".wild.0skar.cz", DNS_TYPE_RP
, BUS_ERROR_NO_SUCH_RR
);
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
);
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");
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");
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
);
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
);
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");