Home | History | Annotate | Line # | Download | only in validator
      1 /*
      2  * validator/val_nsec3.h - validator NSEC3 denial of existence 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  * The functions help with NSEC3 checking, the different NSEC3 proofs
     41  * for denial of existence, and proofs for presence of types.
     42  *
     43  * NSEC3
     44  *                      1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
     45  *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
     46  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     47  * |   Hash Alg.   |     Flags     |          Iterations           |
     48  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     49  * |  Salt Length  |                     Salt                      /
     50  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     51  * |  Hash Length  |             Next Hashed Owner Name            /
     52  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     53  * /                         Type Bit Maps                         /
     54  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     55  *
     56  * NSEC3PARAM
     57  *                      1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
     58  *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
     59  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     60  * |   Hash Alg.   |     Flags     |          Iterations           |
     61  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     62  * |  Salt Length  |                     Salt                      /
     63  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     64  *
     65  */
     66 
     67 #ifndef VALIDATOR_VAL_NSEC3_H
     68 #define VALIDATOR_VAL_NSEC3_H
     69 #include "util/rbtree.h"
     70 #include "util/data/packed_rrset.h"
     71 #include "sldns/rrdef.h"
     72 struct val_env;
     73 struct regional;
     74 struct module_env;
     75 struct module_qstate;
     76 struct ub_packed_rrset_key;
     77 struct reply_info;
     78 struct query_info;
     79 struct key_entry_key;
     80 struct sldns_buffer;
     81 struct val_qstate;
     82 
     83 /**
     84  *     0 1 2 3 4 5 6 7
     85  *    +-+-+-+-+-+-+-+-+
     86  *    |             |O|
     87  *    +-+-+-+-+-+-+-+-+
     88  * The OPT-OUT bit in the NSEC3 flags field.
     89  * If enabled, there can be zero or more unsigned delegations in the span.
     90  * If disabled, there are zero unsigned delegations in the span.
     91  */
     92 #define NSEC3_OPTOUT	0x01
     93 /**
     94  * The unknown flags in the NSEC3 flags field.
     95  * They must be zero, or the NSEC3 is ignored.
     96  */
     97 #define NSEC3_UNKNOWN_FLAGS 0xFE
     98 
     99 /** The SHA1 hash algorithm for NSEC3 */
    100 #define NSEC3_HASH_SHA1	0x01
    101 
    102 /**
    103  * Max number of NSEC3 calculations at once, suspend query for later.
    104  * 8 is low enough and allows for cases where multiple proofs are needed.
    105  */
    106 #define MAX_NSEC3_CALCULATIONS 8
    107 
    108 /**
    109 * Cache table for NSEC3 hashes.
    110 * It keeps a *pointer* to the region its items are allocated.
    111 */
    112 struct nsec3_cache_table {
    113 	rbtree_type* ct;
    114 	struct regional* region;
    115 };
    116 
    117 /**
    118  * Determine if the set of NSEC3 records provided with a response prove NAME
    119  * ERROR. This means that the NSEC3s prove a) the closest encloser exists,
    120  * b) the direct child of the closest encloser towards qname doesn't exist,
    121  * and c) *.closest encloser does not exist.
    122  *
    123  * @param env: module environment with temporary region and buffer.
    124  * @param ve: validator environment, with iteration count settings.
    125  * @param list: array of RRsets, some of which are NSEC3s.
    126  * @param num: number of RRsets in the array to examine.
    127  * @param qinfo: query that is verified for.
    128  * @param kkey: key entry that signed the NSEC3s.
    129  * @param ct: cached hashes table.
    130  * @param calc: current hash calculations.
    131  * @return:
    132  * 	sec_status SECURE of the Name Error is proven by the NSEC3 RRs,
    133  * 	BOGUS if not, INSECURE if all of the NSEC3s could be validly ignored,
    134  * 	UNCHECKED if no more hash calculations are allowed at this point.
    135  */
    136 enum sec_status
    137 nsec3_prove_nameerror(struct module_env* env, struct val_env* ve,
    138 	struct ub_packed_rrset_key** list, size_t num,
    139 	struct query_info* qinfo, struct key_entry_key* kkey,
    140 	struct nsec3_cache_table* ct, int* calc);
    141 
    142 /**
    143  * Determine if the NSEC3s provided in a response prove the NOERROR/NODATA
    144  * status. There are a number of different variants to this:
    145  *
    146  * 1) Normal NODATA -- qname is matched to an NSEC3 record, type is not
    147  * present.
    148  *
    149  * 2) ENT NODATA -- because there must be NSEC3 record for
    150  * empty-non-terminals, this is the same as #1.
    151  *
    152  * 3) NSEC3 ownername NODATA -- qname matched an existing, lone NSEC3
    153  * ownername, but qtype was not NSEC3. NOTE: as of nsec-05, this case no
    154  * longer exists.
    155  *
    156  * 4) Wildcard NODATA -- A wildcard matched the name, but not the type.
    157  *
    158  * 5) Opt-In DS NODATA -- the qname is covered by an opt-in span and qtype ==
    159  * DS. (or maybe some future record with the same parent-side-only property)
    160  *
    161  * @param env: module environment with temporary region and buffer.
    162  * @param ve: validator environment, with iteration count settings.
    163  * @param list: array of RRsets, some of which are NSEC3s.
    164  * @param num: number of RRsets in the array to examine.
    165  * @param qinfo: query that is verified for.
    166  * @param kkey: key entry that signed the NSEC3s.
    167  * @param ct: cached hashes table.
    168  * @param calc: current hash calculations.
    169  * @return:
    170  * 	sec_status SECURE of the proposition is proven by the NSEC3 RRs,
    171  * 	BOGUS if not, INSECURE if all of the NSEC3s could be validly ignored,
    172  * 	UNCHECKED if no more hash calculations are allowed at this point.
    173  */
    174 enum sec_status
    175 nsec3_prove_nodata(struct module_env* env, struct val_env* ve,
    176 	struct ub_packed_rrset_key** list, size_t num,
    177 	struct query_info* qinfo, struct key_entry_key* kkey,
    178 	struct nsec3_cache_table* ct, int* calc);
    179 
    180 /**
    181  * Prove that a positive wildcard match was appropriate (no direct match
    182  * RRset).
    183  *
    184  * @param env: module environment with temporary region and buffer.
    185  * @param ve: validator environment, with iteration count settings.
    186  * @param list: array of RRsets, some of which are NSEC3s.
    187  * @param num: number of RRsets in the array to examine.
    188  * @param qinfo: query that is verified for.
    189  * @param kkey: key entry that signed the NSEC3s.
    190  * @param wc: The purported wildcard that matched. This is the wildcard name
    191  * 	as *.wildcard.name., with the *. label already removed.
    192  * @param ct: cached hashes table.
    193  * @param calc: current hash calculations.
    194  * @return:
    195  * 	sec_status SECURE of the proposition is proven by the NSEC3 RRs,
    196  * 	BOGUS if not, INSECURE if all of the NSEC3s could be validly ignored,
    197  * 	UNCHECKED if no more hash calculations are allowed at this point.
    198  */
    199 enum sec_status
    200 nsec3_prove_wildcard(struct module_env* env, struct val_env* ve,
    201 	struct ub_packed_rrset_key** list, size_t num,
    202 	struct query_info* qinfo, struct key_entry_key* kkey, uint8_t* wc,
    203 	struct nsec3_cache_table* ct, int* calc);
    204 
    205 /**
    206  * Prove that a DS response either had no DS, or wasn't a delegation point.
    207  *
    208  * Fundamentally there are two cases here: normal NODATA and Opt-In NODATA.
    209  *
    210  * @param env: module environment with temporary region and buffer.
    211  * @param ve: validator environment, with iteration count settings.
    212  * @param list: array of RRsets, some of which are NSEC3s.
    213  * @param num: number of RRsets in the array to examine.
    214  * @param qinfo: query that is verified for.
    215  * @param kkey: key entry that signed the NSEC3s.
    216  * @param reason: string for bogus result.
    217  * @param reason_bogus: EDE (RFC8914) code paired with the reason of failure.
    218  * @param qstate: qstate with region.
    219  * @param vq: validator qstate.
    220  * @param ct: cached hashes table.
    221  * @param reasonbuf: buffer to use for fail reason string print.
    222  * @param reasonlen: length of reasonbuf.
    223  * @return:
    224  * 	sec_status SECURE of the proposition is proven by the NSEC3 RRs,
    225  * 	BOGUS if not, INSECURE if all of the NSEC3s could be validly ignored.
    226  * 	or if there was no DS in an insecure (i.e., opt-in) way,
    227  * 	INDETERMINATE if it was clear that this wasn't a delegation point,
    228  * 	UNCHECKED if no more hash calculations are allowed at this point.
    229  */
    230 enum sec_status
    231 nsec3_prove_nods(struct module_env* env, struct val_env* ve,
    232 	struct ub_packed_rrset_key** list, size_t num,
    233 	struct query_info* qinfo, struct key_entry_key* kkey, char** reason,
    234 	sldns_ede_code* reason_bogus, struct module_qstate* qstate,
    235 	struct val_qstate* vq, struct nsec3_cache_table* ct, char* reasonbuf,
    236 	size_t reasonlen);
    237 
    238 /**
    239  * Prove NXDOMAIN or NODATA.
    240  *
    241  * @param env: module environment with temporary region and buffer.
    242  * @param ve: validator environment, with iteration count settings.
    243  * @param list: array of RRsets, some of which are NSEC3s.
    244  * @param num: number of RRsets in the array to examine.
    245  * @param qinfo: query that is verified for.
    246  * @param kkey: key entry that signed the NSEC3s.
    247  * @param nodata: if return value is secure, this indicates if nodata or
    248  * 	nxdomain was proven.
    249  * @param ct: cached hashes table.
    250  * @param calc: current hash calculations.
    251  * @return:
    252  * 	sec_status SECURE of the proposition is proven by the NSEC3 RRs,
    253  * 	BOGUS if not, INSECURE if all of the NSEC3s could be validly ignored,
    254  * 	UNCHECKED if no more hash calculations are allowed at this point.
    255  */
    256 enum sec_status
    257 nsec3_prove_nxornodata(struct module_env* env, struct val_env* ve,
    258 	struct ub_packed_rrset_key** list, size_t num,
    259 	struct query_info* qinfo, struct key_entry_key* kkey, int* nodata,
    260 	struct nsec3_cache_table* ct, int* calc);
    261 
    262 /**
    263  * The NSEC3 hash result storage.
    264  * Consists of an rbtree, with these nodes in it.
    265  * The nodes detail how a set of parameters (from nsec3 rr) plus
    266  * a dname result in a hash.
    267  */
    268 struct nsec3_cached_hash {
    269 	/** rbtree node, key is this structure */
    270 	rbnode_type node;
    271 	/** where are the parameters for conversion, in this rrset data */
    272 	struct ub_packed_rrset_key* nsec3;
    273 	/** where are the parameters for conversion, this RR number in data */
    274 	int rr;
    275 	/** the name to convert */
    276 	uint8_t* dname;
    277 	/** length of the dname */
    278 	size_t dname_len;
    279 	/** the hash result (not base32 encoded) */
    280 	uint8_t* hash;
    281 	/** length of hash in bytes */
    282 	size_t hash_len;
    283 	/** the hash result in base32 encoding */
    284 	uint8_t* b32;
    285 	/** length of base32 encoding (as a label) */
    286 	size_t b32_len;
    287 };
    288 
    289 /**
    290  * Rbtree for hash cache comparison function.
    291  * @param c1: key 1.
    292  * @param c2: key 2.
    293  * @return: comparison code, -1, 0, 1, of the keys.
    294  */
    295 int nsec3_hash_cmp(const void* c1, const void* c2);
    296 
    297 /**
    298  * Initialise the NSEC3 cache table.
    299  * @param ct: the nsec3 cache table.
    300  * @param region: the region where allocations for the table will happen.
    301  * @return true on success, false on malloc error.
    302  */
    303 int nsec3_cache_table_init(struct nsec3_cache_table* ct, struct regional* region);
    304 
    305 /**
    306  * Obtain the hash of an owner name.
    307  * Used internally by the nsec3 proof functions in this file.
    308  * published to enable unit testing of hash algorithms and cache.
    309  *
    310  * @param table: the cache table. Must be initialised at start.
    311  * @param region: scratch region to use for allocation.
    312  * 	This region holds the tree, if you wipe the region, reinit the tree.
    313  * @param buf: temporary buffer.
    314  * @param nsec3: the rrset with parameters
    315  * @param rr: rr number from d that has the NSEC3 parameters to hash to.
    316  * @param dname: name to hash
    317  * 	This pointer is used inside the tree, assumed region-alloced.
    318  * @param dname_len: the length of the name.
    319  * @param hash: the hash node is returned on success.
    320  * @return:
    321  * 	2 on success, hash from cache is returned.
    322  * 	1 on success, newly computed hash is returned.
    323  * 	0 on a malloc failure.
    324  * 	-1 if the NSEC3 rr was badly formatted (i.e. formerr).
    325  */
    326 int nsec3_hash_name(rbtree_type* table, struct regional* region,
    327 	struct sldns_buffer* buf, struct ub_packed_rrset_key* nsec3, int rr,
    328 	uint8_t* dname, size_t dname_len, struct nsec3_cached_hash** hash);
    329 
    330 /**
    331  * Get next owner name, converted to base32 encoding and with the
    332  * zone name (taken from the nsec3 owner name) appended.
    333  * @param rrset: the NSEC3 rrset.
    334  * @param r: the rr num of the nsec3 in the rrset.
    335  * @param buf: buffer to store name in
    336  * @param max: size of buffer.
    337  * @return length of name on success. 0 on failure (buffer too short or
    338  *	bad format nsec3 record).
    339  */
    340 size_t nsec3_get_nextowner_b32(struct ub_packed_rrset_key* rrset, int r,
    341 	uint8_t* buf, size_t max);
    342 
    343 /**
    344  * Convert hash into base32 encoding and with the
    345  * zone name appended.
    346  * @param hash: hashed buffer
    347  * @param hashlen: length of hash
    348  * @param zone: name of zone
    349  * @param zonelen: length of zonename.
    350  * @param buf: buffer to store name in
    351  * @param max: size of buffer.
    352  * @return length of name on success. 0 on failure (buffer too short or
    353  *	bad format nsec3 record).
    354  */
    355 size_t nsec3_hash_to_b32(uint8_t* hash, size_t hashlen, uint8_t* zone,
    356 	size_t zonelen, uint8_t* buf, size_t max);
    357 
    358 /**
    359  * Get NSEC3 parameters out of rr.
    360  * @param rrset: the NSEC3 rrset.
    361  * @param r: the rr num of the nsec3 in the rrset.
    362  * @param algo: nsec3 hash algo.
    363  * @param iter: iteration count.
    364  * @param salt: ptr to salt inside rdata.
    365  * @param saltlen: length of salt.
    366  * @return 0 if bad formatted, unknown nsec3 hash algo, or unknown flags set.
    367  */
    368 int nsec3_get_params(struct ub_packed_rrset_key* rrset, int r,
    369 	int* algo, size_t* iter, uint8_t** salt, size_t* saltlen);
    370 
    371 /**
    372  * Get NSEC3 hashed in a buffer
    373  * @param buf: buffer for temp use.
    374  * @param nm: name to hash
    375  * @param nmlen: length of nm.
    376  * @param algo: algo to use, must be known.
    377  * @param iter: iterations
    378  * @param salt: salt for nsec3
    379  * @param saltlen: length of salt.
    380  * @param res: result of hash stored here.
    381  * @param max: maximum space for result.
    382  * @return 0 on failure, otherwise bytelength stored.
    383  */
    384 size_t nsec3_get_hashed(struct sldns_buffer* buf, uint8_t* nm, size_t nmlen,
    385 	int algo, size_t iter, uint8_t* salt, size_t saltlen, uint8_t* res,
    386 	size_t max);
    387 
    388 /**
    389  * see if NSEC3 RR contains given type
    390  * @param rrset: NSEC3 rrset
    391  * @param r: RR in rrset
    392  * @param type: in host order to check bit for.
    393  * @return true if bit set, false if not or error.
    394  */
    395 int nsec3_has_type(struct ub_packed_rrset_key* rrset, int r, uint16_t type);
    396 
    397 /**
    398  * return if nsec3 RR has the optout flag
    399  * @param rrset: NSEC3 rrset
    400  * @param r: RR in rrset
    401  * @return true if optout, false on error or not optout
    402  */
    403 int nsec3_has_optout(struct ub_packed_rrset_key* rrset, int r);
    404 
    405 /**
    406  * Return nsec3 RR next hashed owner name
    407  * @param rrset: NSEC3 rrset
    408  * @param r: RR in rrset
    409  * @param next: ptr into rdata to next owner hash
    410  * @param nextlen: length of hash.
    411  * @return false on malformed
    412  */
    413 int nsec3_get_nextowner(struct ub_packed_rrset_key* rrset, int r,
    414 	uint8_t** next, size_t* nextlen);
    415 
    416 /**
    417  * nsec3Covers
    418  * Given a hash and a candidate NSEC3Record, determine if that NSEC3Record
    419  * covers the hash. Covers specifically means that the hash is in between
    420  * the owner and next hashes and does not equal either.
    421  *
    422  * @param zone: the zone name.
    423  * @param hash: the hash of the name
    424  * @param rrset: the rrset of the NSEC3.
    425  * @param rr: which rr in the rrset.
    426  * @param buf: temporary buffer.
    427  * @return true if covers, false if not.
    428  */
    429 int nsec3_covers(uint8_t* zone, struct nsec3_cached_hash* hash,
    430 	struct ub_packed_rrset_key* rrset, int rr, struct sldns_buffer* buf);
    431 
    432 #endif /* VALIDATOR_VAL_NSEC3_H */
    433