xref: /freebsd/contrib/unbound/validator/val_utils.h (revision 7ef62cebc2f965b0f640263e179276928885e33d)
1 /*
2  * validator/val_utils.h - validator utility functions.
3  *
4  * Copyright (c) 2007, NLnet Labs. All rights reserved.
5  *
6  * This software is open source.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * Redistributions of source code must retain the above copyright notice,
13  * this list of conditions and the following disclaimer.
14  *
15  * Redistributions in binary form must reproduce the above copyright notice,
16  * this list of conditions and the following disclaimer in the documentation
17  * and/or other materials provided with the distribution.
18  *
19  * Neither the name of the NLNET LABS nor the names of its contributors may
20  * be used to endorse or promote products derived from this software without
21  * specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27  * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
29  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34  */
35 
36 /**
37  * \file
38  *
39  * This file contains helper functions for the validator module.
40  */
41 
42 #ifndef VALIDATOR_VAL_UTILS_H
43 #define VALIDATOR_VAL_UTILS_H
44 #include "util/data/packed_rrset.h"
45 #include "sldns/pkthdr.h"
46 #include "sldns/rrdef.h"
47 struct query_info;
48 struct reply_info;
49 struct val_env;
50 struct module_env;
51 struct module_qstate;
52 struct ub_packed_rrset_key;
53 struct key_entry_key;
54 struct regional;
55 struct val_anchors;
56 struct rrset_cache;
57 struct sock_list;
58 
59 /**
60  * Response classifications for the validator. The different types of proofs.
61  */
62 enum val_classification {
63 	/** Not subtyped yet. */
64 	VAL_CLASS_UNTYPED = 0,
65 	/** Not a recognized subtype. */
66 	VAL_CLASS_UNKNOWN,
67 	/** A positive, direct, response */
68 	VAL_CLASS_POSITIVE,
69 	/** A positive response, with a CNAME/DNAME chain. */
70 	VAL_CLASS_CNAME,
71 	/** A NOERROR/NODATA response. */
72 	VAL_CLASS_NODATA,
73 	/** A NXDOMAIN response. */
74 	VAL_CLASS_NAMEERROR,
75 	/** A CNAME/DNAME chain, and the offset is at the end of it,
76 	 * but there is no answer here, it can be NAMEERROR or NODATA. */
77 	VAL_CLASS_CNAMENOANSWER,
78 	/** A referral, from cache with a nonRD query. */
79 	VAL_CLASS_REFERRAL,
80 	/** A response to a qtype=ANY query. */
81 	VAL_CLASS_ANY
82 };
83 
84 /**
85  * Given a response, classify ANSWER responses into a subtype.
86  * @param query_flags: query flags for the original query.
87  * @param origqinf: query info. The original query name.
88  * @param qinf: query info. The chased query name.
89  * @param rep: response. The original response.
90  * @param skip: offset into the original response answer section.
91  * @return A subtype, all values possible except UNTYPED .
92  * 	Once CNAME type is returned you can increase skip.
93  * 	Then, another CNAME type, CNAME_NOANSWER or POSITIVE are possible.
94  */
95 enum val_classification val_classify_response(uint16_t query_flags,
96 	struct query_info* origqinf, struct query_info* qinf,
97 	struct reply_info* rep, size_t skip);
98 
99 /**
100  * Given a response, determine the name of the "signer". This is primarily
101  * to determine if the response is, in fact, signed at all, and, if so, what
102  * is the name of the most pertinent keyset.
103  *
104  * @param subtype: the type from classify.
105  * @param qinf: query, the chased query name.
106  * @param rep: response to that, original response.
107  * @param cname_skip: how many answer rrsets have been skipped due to CNAME
108  * 	chains being chased around.
109  * @param signer_name:  signer name, if the response is signed
110  * 	(even partially), or null if the response isn't signed.
111  * @param signer_len: length of signer_name of 0 if signer_name is NULL.
112  */
113 void val_find_signer(enum val_classification subtype,
114 	struct query_info* qinf, struct reply_info* rep,
115 	size_t cname_skip, uint8_t** signer_name, size_t* signer_len);
116 
117 /**
118  * Verify RRset with keys from a keyset.
119  * @param env: module environment (scratch buffer)
120  * @param ve: validator environment (verification settings)
121  * @param rrset: what to verify
122  * @param kkey: key_entry to verify with.
123  * @param reason: reason of failure. Fixed string or alloced in scratch.
124  * @param reason_bogus: EDE (RFC8914) code paired with the reason of failure.
125  * @param section: section of packet where this rrset comes from.
126  * @param qstate: qstate with region.
127  * @return security status of verification.
128  */
129 enum sec_status val_verify_rrset_entry(struct module_env* env,
130 	struct val_env* ve, struct ub_packed_rrset_key* rrset,
131 	struct key_entry_key* kkey, char** reason, sldns_ede_code *reason_bogus,
132 	sldns_pkt_section section, struct module_qstate* qstate);
133 
134 /**
135  * Verify DNSKEYs with DS rrset. Like val_verify_new_DNSKEYs but
136  * returns a sec_status instead of a key_entry.
137  * @param env: module environment (scratch buffer)
138  * @param ve: validator environment (verification settings)
139  * @param dnskey_rrset: DNSKEY rrset to verify
140  * @param ds_rrset: DS rrset to verify with.
141  * @param sigalg: if nonNULL provide downgrade protection otherwise one
142  *   algorithm is enough.  The list of signalled algorithms is returned,
143  *   must have enough space for ALGO_NEEDS_MAX+1.
144  * @param reason: reason of failure. Fixed string or alloced in scratch.
145  * @param reason_bogus: EDE (RFC8914) code paired with the reason of failure.
146  * @param qstate: qstate with region.
147  * @return: sec_status_secure if a DS matches.
148  *     sec_status_insecure if end of trust (i.e., unknown algorithms).
149  *     sec_status_bogus if it fails.
150  */
151 enum sec_status val_verify_DNSKEY_with_DS(struct module_env* env,
152     struct val_env* ve, struct ub_packed_rrset_key* dnskey_rrset,
153     struct ub_packed_rrset_key* ds_rrset, uint8_t* sigalg, char** reason,
154     sldns_ede_code *reason_bogus, struct module_qstate* qstate);
155 
156 /**
157  * Verify DNSKEYs with DS and DNSKEY rrset.  Like val_verify_DNSKEY_with_DS
158  * but for a trust anchor.
159  * @param env: module environment (scratch buffer)
160  * @param ve: validator environment (verification settings)
161  * @param dnskey_rrset: DNSKEY rrset to verify
162  * @param ta_ds: DS rrset to verify with.
163  * @param ta_dnskey: DNSKEY rrset to verify with.
164  * @param sigalg: if nonNULL provide downgrade protection otherwise one
165  *   algorithm is enough.  The list of signalled algorithms is returned,
166  *   must have enough space for ALGO_NEEDS_MAX+1.
167  * @param reason: reason of failure. Fixed string or alloced in scratch.
168 * @param reason_bogus: EDE (RFC8914) code paired with the reason of failure.
169  * @param qstate: qstate with region.
170  * @return: sec_status_secure if a DS matches.
171  *     sec_status_insecure if end of trust (i.e., unknown algorithms).
172  *     sec_status_bogus if it fails.
173  */
174 enum sec_status val_verify_DNSKEY_with_TA(struct module_env* env,
175     struct val_env* ve, struct ub_packed_rrset_key* dnskey_rrset,
176     struct ub_packed_rrset_key* ta_ds,
177     struct ub_packed_rrset_key* ta_dnskey, uint8_t* sigalg, char** reason,
178     sldns_ede_code *reason_bogus, struct module_qstate* qstate);
179 
180 /**
181  * Verify new DNSKEYs with DS rrset. The DS contains hash values that should
182  * match the DNSKEY keys.
183  * match the DS to a DNSKEY and verify the DNSKEY rrset with that key.
184  *
185  * @param region: where to allocate key entry result.
186  * @param env: module environment (scratch buffer)
187  * @param ve: validator environment (verification settings)
188  * @param dnskey_rrset: DNSKEY rrset to verify
189  * @param ds_rrset: DS rrset to verify with.
190  * @param downprot: if true provide downgrade protection otherwise one
191  *   algorithm is enough.
192  * @param reason: reason of failure. Fixed string or alloced in scratch.
193  * @param reason_bogus: EDE (RFC8914) code paired with the reason of failure.
194  * @param qstate: qstate with region.
195  * @return a KeyEntry. This will either contain the now trusted
196  *         dnskey_rrset, a "null" key entry indicating that this DS
197  *         rrset/DNSKEY pair indicate an secure end to the island of trust
198  *         (i.e., unknown algorithms), or a "bad" KeyEntry if the dnskey
199  *         rrset fails to verify. Note that the "null" response should
200  *         generally only occur in a private algorithm scenario: normally
201  *         this sort of thing is checked before fetching the matching DNSKEY
202  *         rrset.
203  *         if downprot is set, a key entry with an algo list is made.
204  */
205 struct key_entry_key* val_verify_new_DNSKEYs(struct regional* region,
206     struct module_env* env, struct val_env* ve,
207     struct ub_packed_rrset_key* dnskey_rrset,
208     struct ub_packed_rrset_key* ds_rrset, int downprot, char** reason,
209     sldns_ede_code *reason_bogus, struct module_qstate* qstate);
210 
211 /**
212  * Verify rrset with trust anchor: DS and DNSKEY rrset.
213  *
214  * @param region: where to allocate key entry result.
215  * @param env: module environment (scratch buffer)
216  * @param ve: validator environment (verification settings)
217  * @param dnskey_rrset: DNSKEY rrset to verify
218  * @param ta_ds_rrset: DS rrset to verify with.
219  * @param ta_dnskey_rrset: the DNSKEY rrset to verify with.
220  * @param downprot: if true provide downgrade protection otherwise one
221  *   algorithm is enough.
222  * @param reason: reason of failure. Fixed string or alloced in scratch.
223  * @param reason_bogus: EDE (RFC8914) code paired with the reason of failure.
224  * @param qstate: qstate with region.
225  * @return a KeyEntry. This will either contain the now trusted
226  *         dnskey_rrset, a "null" key entry indicating that this DS
227  *         rrset/DNSKEY pair indicate an secure end to the island of trust
228  *         (i.e., unknown algorithms), or a "bad" KeyEntry if the dnskey
229  *         rrset fails to verify. Note that the "null" response should
230  *         generally only occur in a private algorithm scenario: normally
231  *         this sort of thing is checked before fetching the matching DNSKEY
232  *         rrset.
233  *         if downprot is set, a key entry with an algo list is made.
234  */
235 struct key_entry_key* val_verify_new_DNSKEYs_with_ta(struct regional* region,
236     struct module_env* env, struct val_env* ve,
237     struct ub_packed_rrset_key* dnskey_rrset,
238     struct ub_packed_rrset_key* ta_ds_rrset,
239     struct ub_packed_rrset_key* ta_dnskey_rrset, int downprot,
240     char** reason, sldns_ede_code *reason_bogus, struct module_qstate* qstate);
241 
242 /**
243  * Determine if DS rrset is usable for validator or not.
244  * Returns true if the algorithms for key and DShash are supported,
245  * for at least one RR.
246  *
247  * @param ds_rrset: the newly received DS rrset.
248  * @return true or false if not usable.
249  */
250 int val_dsset_isusable(struct ub_packed_rrset_key* ds_rrset);
251 
252 /**
253  * Determine by looking at a signed RRset whether or not the RRset name was
254  * the result of a wildcard expansion. If so, return the name of the
255  * generating wildcard.
256  *
257  * @param rrset The rrset to check.
258  * @param wc: the wildcard name, if the rrset was synthesized from a wildcard.
259  *         unchanged if not.  The wildcard name, without "*." in front, is
260  *         returned. This is a pointer into the rrset owner name.
261  * @param wc_len: the length of the returned wildcard name.
262  * @return false if the signatures are inconsistent in indicating the
263  * 	wildcard status; possible spoofing of wildcard response for other
264  * 	responses is being tried. We lost the status which rrsig was verified
265  * 	after the verification routine finished, so we simply check if
266  * 	the signatures are consistent; inserting a fake signature is a denial
267  * 	of service; but in that you could also have removed the real
268  * 	signature anyway.
269  */
270 int val_rrset_wildcard(struct ub_packed_rrset_key* rrset, uint8_t** wc,
271 	size_t* wc_len);
272 
273 /**
274  * Chase the cname to the next query name.
275  * @param qchase: the current query name, updated to next target.
276  * @param rep: original message reply to look at CNAMEs.
277  * @param cname_skip: the skip into the answer section. Updated to skip
278  * 	DNAME and CNAME to the next part of the answer.
279  * @return false on error (bad rdata).
280  */
281 int val_chase_cname(struct query_info* qchase, struct reply_info* rep,
282 	size_t* cname_skip);
283 
284 /**
285  * Fill up the chased reply with the content from the original reply;
286  * as pointers to those rrsets. Select the part after the cname_skip into
287  * the answer section, NS and AR sections that are signed with same signer.
288  *
289  * @param chase: chased reply, filled up.
290  * @param orig: original reply.
291  * @param cname_skip: which part of the answer section to skip.
292  * 	The skipped part contains CNAME(and DNAME)s that have been chased.
293  * @param name: the signer name to look for.
294  * @param len: length of name.
295  * @param signer: signer name or NULL if an unsigned RRset is considered.
296  *	If NULL, rrsets with the lookup name are copied over.
297  */
298 void val_fill_reply(struct reply_info* chase, struct reply_info* orig,
299 	size_t cname_skip, uint8_t* name, size_t len, uint8_t* signer);
300 
301 /**
302  * Remove rrset with index from reply, from the authority section.
303  * @param rep: reply to remove it from.
304  * @param index: rrset to remove, must be in the authority section.
305  */
306 void val_reply_remove_auth(struct reply_info* rep, size_t index);
307 
308 /**
309  * Remove all unsigned or non-secure status rrsets from NS and AR sections.
310  * So that unsigned data does not get let through to clients, when we have
311  * found the data to be secure.
312  *
313  * @param env: environment with cleaning options.
314  * @param rep: reply to dump all nonsecure stuff out of.
315  */
316 void val_check_nonsecure(struct module_env* env, struct reply_info* rep);
317 
318 /**
319  * Mark all unchecked rrset entries not below a trust anchor as indeterminate.
320  * Only security==unchecked rrsets are updated.
321  * @param rep: the reply with rrsets.
322  * @param anchors: the trust anchors.
323  * @param r: rrset cache to store updated security status into.
324  * @param env: module environment
325  */
326 void val_mark_indeterminate(struct reply_info* rep,
327 	struct val_anchors* anchors, struct rrset_cache* r,
328 	struct module_env* env);
329 
330 /**
331  * Mark all unchecked rrset entries below a NULL key entry as insecure.
332  * Only security==unchecked rrsets are updated.
333  * @param rep: the reply with rrsets.
334  * @param kname: end of secure space name.
335  * @param r: rrset cache to store updated security status into.
336  * @param env: module environment
337  */
338 void val_mark_insecure(struct reply_info* rep, uint8_t* kname,
339 	struct rrset_cache* r, struct module_env* env);
340 
341 /**
342  * Find next unchecked rrset position, return it for skip.
343  * @param rep: the original reply to look into.
344  * @param skip: the skip now.
345  * @return new skip, which may be at the rep->rrset_count position to signal
346  * 	there are no unchecked items.
347  */
348 size_t val_next_unchecked(struct reply_info* rep, size_t skip);
349 
350 /**
351  * Find the signer name for an RRset.
352  * @param rrset: the rrset.
353  * @param sname: signer name is returned or NULL if not signed.
354  * @param slen: length of sname (or 0).
355  */
356 void val_find_rrset_signer(struct ub_packed_rrset_key* rrset, uint8_t** sname,
357 	size_t* slen);
358 
359 /**
360  * Get string to denote the classification result.
361  * @param subtype: from classification function.
362  * @return static string to describe the classification.
363  */
364 const char* val_classification_to_string(enum val_classification subtype);
365 
366 /**
367  * Add existing list to blacklist.
368  * @param blacklist: the blacklist with result
369  * @param region: the region where blacklist is allocated.
370  *	Allocation failures are logged.
371  * @param origin: origin list to add, if NULL, a cache-entry is added to
372  *   the blacklist to stop cache from being used.
373  * @param cross: if true this is a cross-qstate copy, and the 'origin'
374  *   list is not allocated in the same region as the blacklist.
375  */
376 void val_blacklist(struct sock_list** blacklist, struct regional* region,
377 	struct sock_list* origin, int cross);
378 
379 /**
380  * check if has dnssec info, and if it has signed nsecs. gives error reason.
381  * @param rep: reply to check.
382  * @param reason: returned on fail.
383  * @return false if message has no signed nsecs.  Can not prove negatives.
384  */
385 int val_has_signed_nsecs(struct reply_info* rep, char** reason);
386 
387 /**
388  * Return algo number for favorite (best) algorithm that we support in DS.
389  * @param ds_rrset: the DSes in this rrset are inspected and best algo chosen.
390  * @return algo number or 0 if none supported. 0 is unused as algo number.
391  */
392 int val_favorite_ds_algo(struct ub_packed_rrset_key* ds_rrset);
393 
394 /**
395  * Find DS denial message in cache.  Saves new qstate allocation and allows
396  * the validator to use partial content which is not enough to construct a
397  * message for network (or user) consumption.  Without SOA for example,
398  * which is a common occurrence in the unbound code since the referrals contain
399  * NSEC/NSEC3 rrs without the SOA element, thus do not allow synthesis of a
400  * full negative reply, but do allow synthesis of sufficient proof.
401  * @param env: query env with caches and time.
402  * @param nm: name of DS record sought.
403  * @param nmlen: length of name.
404  * @param c: class of DS RR.
405  * @param region: where to allocate result.
406  * @param topname: name of the key that is currently in use, that will get
407  *	used to validate the result, and thus no higher entries from the
408  *	negative cache need to be examined.
409  * @return a dns_msg on success. NULL on failure.
410  */
411 struct dns_msg* val_find_DS(struct module_env* env, uint8_t* nm, size_t nmlen,
412 	uint16_t c, struct regional* region, uint8_t* topname);
413 
414 #endif /* VALIDATOR_VAL_UTILS_H */
415