]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/resolve/dns-type.c
resolved: explicitly refuse zone transfers using the bus API
[thirdparty/systemd.git] / src / resolve / dns-type.c
1 /***
2 This file is part of systemd.
3
4 Copyright 2014 Zbigniew Jędrzejewski-Szmek
5
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
10
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
18 ***/
19
20 #include <sys/socket.h>
21
22 #include "dns-type.h"
23 #include "parse-util.h"
24 #include "string-util.h"
25
26 typedef const struct {
27 uint16_t type;
28 const char *name;
29 } dns_type;
30
31 static const struct dns_type_name *
32 lookup_dns_type (register const char *str, register unsigned int len);
33
34 #include "dns_type-from-name.h"
35 #include "dns_type-to-name.h"
36
37 int dns_type_from_string(const char *s) {
38 const struct dns_type_name *sc;
39
40 assert(s);
41
42 sc = lookup_dns_type(s, strlen(s));
43 if (sc)
44 return sc->id;
45
46 s = startswith_no_case(s, "TYPE");
47 if (s) {
48 unsigned x;
49
50 if (safe_atou(s, &x) >= 0 &&
51 x <= UINT16_MAX)
52 return (int) x;
53 }
54
55 return _DNS_TYPE_INVALID;
56 }
57
58 bool dns_type_is_pseudo(uint16_t type) {
59
60 /* Checks whether the specified type is a "pseudo-type". What
61 * a "pseudo-type" precisely is, is defined only very weakly,
62 * but apparently entails all RR types that are not actually
63 * stored as RRs on the server and should hence also not be
64 * cached. We use this list primarily to validate NSEC type
65 * bitfields, and to verify what to cache. */
66
67 return IN_SET(type,
68 0, /* A Pseudo RR type, according to RFC 2931 */
69 DNS_TYPE_ANY,
70 DNS_TYPE_AXFR,
71 DNS_TYPE_IXFR,
72 DNS_TYPE_OPT,
73 DNS_TYPE_TSIG,
74 DNS_TYPE_TKEY
75 );
76 }
77
78 bool dns_class_is_pseudo(uint16_t class) {
79 return class == DNS_TYPE_ANY;
80 }
81
82 bool dns_type_is_valid_query(uint16_t type) {
83
84 /* The types valid as questions in packets */
85
86 return !IN_SET(type,
87 0,
88 DNS_TYPE_OPT,
89 DNS_TYPE_TSIG,
90 DNS_TYPE_TKEY,
91
92 /* RRSIG are technically valid as questions, but we refuse doing explicit queries for them, as
93 * they aren't really payload, but signatures for payload, and cannot be validated on their
94 * own. After all they are the signatures, and have no signatures of their own validating
95 * them. */
96 DNS_TYPE_RRSIG);
97 }
98
99 bool dns_type_is_zone_transer(uint16_t type) {
100
101 /* Zone transfers, either normal or incremental */
102
103 return IN_SET(type,
104 DNS_TYPE_AXFR,
105 DNS_TYPE_IXFR);
106 }
107
108 bool dns_type_is_valid_rr(uint16_t type) {
109
110 /* The types valid as RR in packets (but not necessarily
111 * stored on servers). */
112
113 return !IN_SET(type,
114 DNS_TYPE_ANY,
115 DNS_TYPE_AXFR,
116 DNS_TYPE_IXFR);
117 }
118
119 bool dns_class_is_valid_rr(uint16_t class) {
120 return class != DNS_CLASS_ANY;
121 }
122
123 bool dns_type_may_redirect(uint16_t type) {
124 /* The following record types should never be redirected using
125 * CNAME/DNAME RRs. See
126 * <https://tools.ietf.org/html/rfc4035#section-2.5>. */
127
128 if (dns_type_is_pseudo(type))
129 return false;
130
131 return !IN_SET(type,
132 DNS_TYPE_CNAME,
133 DNS_TYPE_DNAME,
134 DNS_TYPE_NSEC3,
135 DNS_TYPE_NSEC,
136 DNS_TYPE_RRSIG,
137 DNS_TYPE_NXT,
138 DNS_TYPE_SIG,
139 DNS_TYPE_KEY);
140 }
141
142 bool dns_type_may_wildcard(uint16_t type) {
143
144 /* The following records may not be expanded from wildcard RRsets */
145
146 if (dns_type_is_pseudo(type))
147 return false;
148
149 return !IN_SET(type,
150 DNS_TYPE_NSEC3,
151 DNS_TYPE_SOA,
152
153 /* Prohibited by https://tools.ietf.org/html/rfc4592#section-4.4 */
154 DNS_TYPE_DNAME);
155 }
156
157 bool dns_type_apex_only(uint16_t type) {
158
159 /* Returns true for all RR types that may only appear signed in a zone apex */
160
161 return IN_SET(type,
162 DNS_TYPE_SOA,
163 DNS_TYPE_NS, /* this one can appear elsewhere, too, but not signed */
164 DNS_TYPE_DNSKEY,
165 DNS_TYPE_NSEC3PARAM);
166 }
167
168 bool dns_type_is_dnssec(uint16_t type) {
169 return IN_SET(type,
170 DNS_TYPE_DS,
171 DNS_TYPE_DNSKEY,
172 DNS_TYPE_RRSIG,
173 DNS_TYPE_NSEC,
174 DNS_TYPE_NSEC3,
175 DNS_TYPE_NSEC3PARAM);
176 }
177
178 bool dns_type_is_obsolete(uint16_t type) {
179 return IN_SET(type,
180 /* Obsoleted by RFC 973 */
181 DNS_TYPE_MD,
182 DNS_TYPE_MF,
183 DNS_TYPE_MAILA,
184
185 /* Kinda obsoleted by RFC 2505 */
186 DNS_TYPE_MB,
187 DNS_TYPE_MG,
188 DNS_TYPE_MR,
189 DNS_TYPE_MINFO,
190 DNS_TYPE_MAILB,
191
192 /* RFC1127 kinda obsoleted this by recommending against its use */
193 DNS_TYPE_WKS,
194
195 /* Declared historical by RFC 6563 */
196 DNS_TYPE_A6,
197
198 /* Obsoleted by DNSSEC-bis */
199 DNS_TYPE_NXT,
200
201 /* RFC 1035 removed support for concepts that needed this from RFC 883 */
202 DNS_TYPE_NULL);
203 }
204
205 bool dns_type_needs_authentication(uint16_t type) {
206
207 /* Returns true for all (non-obsolete) RR types where records are not useful if they aren't
208 * authenticated. I.e. everything that contains crypto keys. */
209
210 return IN_SET(type,
211 DNS_TYPE_CERT,
212 DNS_TYPE_SSHFP,
213 DNS_TYPE_IPSECKEY,
214 DNS_TYPE_DS,
215 DNS_TYPE_DNSKEY,
216 DNS_TYPE_TLSA,
217 DNS_TYPE_CDNSKEY,
218 DNS_TYPE_OPENPGPKEY,
219 DNS_TYPE_CAA);
220 }
221
222 int dns_type_to_af(uint16_t t) {
223 switch (t) {
224
225 case DNS_TYPE_A:
226 return AF_INET;
227
228 case DNS_TYPE_AAAA:
229 return AF_INET6;
230
231 case DNS_TYPE_ANY:
232 return AF_UNSPEC;
233
234 default:
235 return -EINVAL;
236 }
237 }
238
239 const char *dns_class_to_string(uint16_t class) {
240
241 switch (class) {
242
243 case DNS_CLASS_IN:
244 return "IN";
245
246 case DNS_CLASS_ANY:
247 return "ANY";
248 }
249
250 return NULL;
251 }
252
253 int dns_class_from_string(const char *s) {
254
255 if (!s)
256 return _DNS_CLASS_INVALID;
257
258 if (strcaseeq(s, "IN"))
259 return DNS_CLASS_IN;
260 else if (strcaseeq(s, "ANY"))
261 return DNS_CLASS_ANY;
262
263 return _DNS_CLASS_INVALID;
264 }
265
266 const char* tlsa_cert_usage_to_string(uint8_t cert_usage) {
267
268 switch (cert_usage) {
269
270 case 0:
271 return "CA constraint";
272
273 case 1:
274 return "Service certificate constraint";
275
276 case 2:
277 return "Trust anchor assertion";
278
279 case 3:
280 return "Domain-issued certificate";
281
282 case 4 ... 254:
283 return "Unassigned";
284
285 case 255:
286 return "Private use";
287 }
288
289 return NULL; /* clang cannot count that we covered everything */
290 }
291
292 const char* tlsa_selector_to_string(uint8_t selector) {
293 switch (selector) {
294
295 case 0:
296 return "Full Certificate";
297
298 case 1:
299 return "SubjectPublicKeyInfo";
300
301 case 2 ... 254:
302 return "Unassigned";
303
304 case 255:
305 return "Private use";
306 }
307
308 return NULL;
309 }
310
311 const char* tlsa_matching_type_to_string(uint8_t selector) {
312
313 switch (selector) {
314
315 case 0:
316 return "No hash used";
317
318 case 1:
319 return "SHA-256";
320
321 case 2:
322 return "SHA-512";
323
324 case 3 ... 254:
325 return "Unassigned";
326
327 case 255:
328 return "Private use";
329 }
330
331 return NULL;
332 }