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