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