Home | History | Annotate | Line # | Download | only in validator
      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