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