This file contains helper functions for the validator module. More...
Data Structures | |
| struct | nsec3_cache_table |
| Cache table for NSEC3 hashes. More... | |
| struct | nsec3_cached_hash |
| The NSEC3 hash result storage. More... | |
Macros | |
| #define | NSEC3_OPTOUT 0x01 |
| #define | NSEC3_UNKNOWN_FLAGS 0xFE |
| The unknown flags in the NSEC3 flags field. | |
| #define | NSEC3_HASH_SHA1 0x01 |
| The SHA1 hash algorithm for NSEC3. | |
Functions | |
| enum sec_status | nsec3_prove_nameerror (struct module_env *env, struct val_env *ve, struct ub_packed_rrset_key **list, size_t num, struct query_info *qinfo, struct key_entry_key *kkey, struct nsec3_cache_table *ct, int *calc) |
| Determine if the set of NSEC3 records provided with a response prove NAME ERROR. | |
| enum sec_status | nsec3_prove_nodata (struct module_env *env, struct val_env *ve, struct ub_packed_rrset_key **list, size_t num, struct query_info *qinfo, struct key_entry_key *kkey, struct nsec3_cache_table *ct, int *calc) |
| Determine if the NSEC3s provided in a response prove the NOERROR/NODATA status. | |
| enum sec_status | nsec3_prove_wildcard (struct module_env *env, struct val_env *ve, struct ub_packed_rrset_key **list, size_t num, struct query_info *qinfo, struct key_entry_key *kkey, uint8_t *wc, struct nsec3_cache_table *ct, int *calc) |
| Prove that a positive wildcard match was appropriate (no direct match RRset). | |
| enum sec_status | nsec3_prove_nods (struct module_env *env, struct val_env *ve, struct ub_packed_rrset_key **list, size_t num, struct query_info *qinfo, struct key_entry_key *kkey, char **reason, sldns_ede_code *reason_bogus, struct module_qstate *qstate, struct nsec3_cache_table *ct, char *reasonbuf, size_t reasonlen) |
| Prove that a DS response either had no DS, or wasn't a delegation point. | |
| enum sec_status | nsec3_prove_nxornodata (struct module_env *env, struct val_env *ve, struct ub_packed_rrset_key **list, size_t num, struct query_info *qinfo, struct key_entry_key *kkey, int *nodata, struct nsec3_cache_table *ct, int *calc) |
| Prove NXDOMAIN or NODATA. | |
| int | nsec3_hash_cmp (const void *c1, const void *c2) |
| Rbtree for hash cache comparison function. | |
| int | nsec3_cache_table_init (struct nsec3_cache_table *ct, struct regional *region) |
| Initialise the NSEC3 cache table. | |
| int | nsec3_hash_name (rbtree_type *table, struct regional *region, struct sldns_buffer *buf, struct ub_packed_rrset_key *nsec3, int rr, uint8_t *dname, size_t dname_len, struct nsec3_cached_hash **hash) |
| Obtain the hash of an owner name. | |
| size_t | nsec3_get_nextowner_b32 (struct ub_packed_rrset_key *rrset, int r, uint8_t *buf, size_t max) |
| Get next owner name, converted to base32 encoding and with the zone name (taken from the nsec3 owner name) appended. | |
| size_t | nsec3_hash_to_b32 (uint8_t *hash, size_t hashlen, uint8_t *zone, size_t zonelen, uint8_t *buf, size_t max) |
| Convert hash into base32 encoding and with the zone name appended. | |
| int | nsec3_get_params (struct ub_packed_rrset_key *rrset, int r, int *algo, size_t *iter, uint8_t **salt, size_t *saltlen) |
| Get NSEC3 parameters out of rr. | |
| size_t | nsec3_get_hashed (struct sldns_buffer *buf, uint8_t *nm, size_t nmlen, int algo, size_t iter, uint8_t *salt, size_t saltlen, uint8_t *res, size_t max) |
| Get NSEC3 hashed in a buffer. | |
| int | nsec3_has_type (struct ub_packed_rrset_key *rrset, int r, uint16_t type) |
| see if NSEC3 RR contains given type | |
| int | nsec3_has_optout (struct ub_packed_rrset_key *rrset, int r) |
| return if nsec3 RR has the optout flag | |
| int | nsec3_get_nextowner (struct ub_packed_rrset_key *rrset, int r, uint8_t **next, size_t *nextlen) |
| Return nsec3 RR next hashed owner name. | |
| int | nsec3_covers (uint8_t *zone, struct nsec3_cached_hash *hash, struct ub_packed_rrset_key *rrset, int rr, struct sldns_buffer *buf) |
| nsec3Covers Given a hash and a candidate NSEC3Record, determine if that NSEC3Record covers the hash. | |
This file contains helper functions for the validator module.
The functions help with NSEC3 checking, the different NSEC3 proofs for denial of existence, and proofs for presence of types.
NSEC3 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 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 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Hash Alg. | Flags | Iterations | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Salt Length | Salt / +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Hash Length | Next Hashed Owner Name / +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ / Type Bit Maps / +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
NSEC3PARAM 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 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 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Hash Alg. | Flags | Iterations | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Salt Length | Salt / +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| #define NSEC3_OPTOUT 0x01 |
0 1 2 3 4 5 6 7
+-+-+-+-+-+-+-+-+ | |O| +-+-+-+-+-+-+-+-+ The OPT-OUT bit in the NSEC3 flags field. If enabled, there can be zero or more unsigned delegations in the span. If disabled, there are zero unsigned delegations in the span.
| #define NSEC3_UNKNOWN_FLAGS 0xFE |
The unknown flags in the NSEC3 flags field.
They must be zero, or the NSEC3 is ignored.
| enum sec_status nsec3_prove_nameerror | ( | struct module_env * | env, |
| struct val_env * | ve, | ||
| struct ub_packed_rrset_key ** | list, | ||
| size_t | num, | ||
| struct query_info * | qinfo, | ||
| struct key_entry_key * | kkey, | ||
| struct nsec3_cache_table * | ct, | ||
| int * | calc | ||
| ) |
Determine if the set of NSEC3 records provided with a response prove NAME ERROR.
This means that the NSEC3s prove a) the closest encloser exists, b) the direct child of the closest encloser towards qname doesn't exist, and c) *.closest encloser does not exist.
| env | module environment with temporary region and buffer. |
| ve | validator environment, with iteration count settings. |
| list | array of RRsets, some of which are NSEC3s. |
| num | number of RRsets in the array to examine. |
| qinfo | query that is verified for. |
| kkey | key entry that signed the NSEC3s. |
| ct | cached hashes table. |
| calc | current hash calculations. |
References filter_init(), key_entry_isgood(), nsec3_filter::list, log_nametypeclass(), nsec3_do_prove_nameerror(), nsec3_iteration_count_high(), nsec3_filter::num, sec_status_bogus, sec_status_insecure, VERB_ALGO, and nsec3_filter::zone.
Referenced by validate_nameerror_response().
| enum sec_status nsec3_prove_nodata | ( | struct module_env * | env, |
| struct val_env * | ve, | ||
| struct ub_packed_rrset_key ** | list, | ||
| size_t | num, | ||
| struct query_info * | qinfo, | ||
| struct key_entry_key * | kkey, | ||
| struct nsec3_cache_table * | ct, | ||
| int * | calc | ||
| ) |
Determine if the NSEC3s provided in a response prove the NOERROR/NODATA status.
There are a number of different variants to this:
1) Normal NODATA – qname is matched to an NSEC3 record, type is not present.
2) ENT NODATA – because there must be NSEC3 record for empty-non-terminals, this is the same as #1.
3) NSEC3 ownername NODATA – qname matched an existing, lone NSEC3 ownername, but qtype was not NSEC3. NOTE: as of nsec-05, this case no longer exists.
4) Wildcard NODATA – A wildcard matched the name, but not the type.
5) Opt-In DS NODATA – the qname is covered by an opt-in span and qtype == DS. (or maybe some future record with the same parent-side-only property)
| env | module environment with temporary region and buffer. |
| ve | validator environment, with iteration count settings. |
| list | array of RRsets, some of which are NSEC3s. |
| num | number of RRsets in the array to examine. |
| qinfo | query that is verified for. |
| kkey | key entry that signed the NSEC3s. |
| ct | cached hashes table. |
| calc | current hash calculations. |
References filter_init(), key_entry_isgood(), nsec3_filter::list, nsec3_do_prove_nodata(), nsec3_iteration_count_high(), nsec3_filter::num, sec_status_bogus, sec_status_insecure, and nsec3_filter::zone.
Referenced by validate_nodata_response().
| enum sec_status nsec3_prove_wildcard | ( | struct module_env * | env, |
| struct val_env * | ve, | ||
| struct ub_packed_rrset_key ** | list, | ||
| size_t | num, | ||
| struct query_info * | qinfo, | ||
| struct key_entry_key * | kkey, | ||
| uint8_t * | wc, | ||
| struct nsec3_cache_table * | ct, | ||
| int * | calc | ||
| ) |
Prove that a positive wildcard match was appropriate (no direct match RRset).
| env | module environment with temporary region and buffer. |
| ve | validator environment, with iteration count settings. |
| list | array of RRsets, some of which are NSEC3s. |
| num | number of RRsets in the array to examine. |
| qinfo | query that is verified for. |
| kkey | key entry that signed the NSEC3s. |
| wc | The purported wildcard that matched. This is the wildcard name as *.wildcard.name., with the *. label already removed. |
| ct | cached hashes table. |
| calc | current hash calculations. |
References ce_response::ce, dname_count_size_labels(), filter_init(), find_covering_nsec3(), key_entry_isgood(), MAX_NSEC3_CALCULATIONS, MAX_NSEC3_ERRORS, next_closer(), nsec3_has_optout(), nsec3_iteration_count_high(), query_info::qname, query_info::qname_len, sec_status_bogus, sec_status_insecure, sec_status_secure, sec_status_unchecked, VERB_ALGO, verbose(), and nsec3_filter::zone.
Referenced by validate_any_response(), validate_cname_response(), and validate_positive_response().
| enum sec_status nsec3_prove_nods | ( | struct module_env * | env, |
| struct val_env * | ve, | ||
| struct ub_packed_rrset_key ** | list, | ||
| size_t | num, | ||
| struct query_info * | qinfo, | ||
| struct key_entry_key * | kkey, | ||
| char ** | reason, | ||
| sldns_ede_code * | reason_bogus, | ||
| struct module_qstate * | qstate, | ||
| struct nsec3_cache_table * | ct, | ||
| char * | reasonbuf, | ||
| size_t | reasonlen | ||
| ) |
Prove that a DS response either had no DS, or wasn't a delegation point.
Fundamentally there are two cases here: normal NODATA and Opt-In NODATA.
| env | module environment with temporary region and buffer. |
| ve | validator environment, with iteration count settings. |
| list | array of RRsets, some of which are NSEC3s. |
| num | number of RRsets in the array to examine. |
| qinfo | query that is verified for. |
| kkey | key entry that signed the NSEC3s. |
| reason | string for bogus result. |
| reason_bogus | EDE (RFC8914) code paired with the reason of failure. |
| qstate | qstate with region. |
| ct | cached hashes table. |
| reasonbuf | buffer to use for fail reason string print. |
| reasonlen | length of reasonbuf. |
References ce_response::ce, filter_init(), find_matching_nsec3(), key_entry_isgood(), LDNS_RR_TYPE_DS, LDNS_RR_TYPE_NS, LDNS_RR_TYPE_SOA, list_is_secure(), log_assert, MAX_NSEC3_CALCULATIONS, MAX_NSEC3_ERRORS, ce_response::nc_rr, ce_response::nc_rrset, nsec3_has_optout(), nsec3_has_type(), nsec3_iteration_count_high(), nsec3_prove_closest_encloser(), query_info::qname, query_info::qname_len, query_info::qtype, sec_status_bogus, sec_status_indeterminate, sec_status_insecure, sec_status_secure, sec_status_unchecked, VERB_ALGO, verbose(), and nsec3_filter::zone.
Referenced by ds_response_to_ke().
| enum sec_status nsec3_prove_nxornodata | ( | struct module_env * | env, |
| struct val_env * | ve, | ||
| struct ub_packed_rrset_key ** | list, | ||
| size_t | num, | ||
| struct query_info * | qinfo, | ||
| struct key_entry_key * | kkey, | ||
| int * | nodata, | ||
| struct nsec3_cache_table * | ct, | ||
| int * | calc | ||
| ) |
Prove NXDOMAIN or NODATA.
| env | module environment with temporary region and buffer. |
| ve | validator environment, with iteration count settings. |
| list | array of RRsets, some of which are NSEC3s. |
| num | number of RRsets in the array to examine. |
| qinfo | query that is verified for. |
| kkey | key entry that signed the NSEC3s. |
| nodata | if return value is secure, this indicates if nodata or nxdomain was proven. |
| ct | cached hashes table. |
| calc | current hash calculations. |
References filter_init(), key_entry_isgood(), nsec3_filter::list, nsec3_do_prove_nameerror(), nsec3_do_prove_nodata(), nsec3_iteration_count_high(), nsec3_filter::num, sec_status_bogus, sec_status_insecure, sec_status_secure, sec_status_unchecked, and nsec3_filter::zone.
Referenced by validate_cname_noanswer_response().
| int nsec3_hash_cmp | ( | const void * | c1, |
| const void * | c2 | ||
| ) |
Rbtree for hash cache comparison function.
| c1 | key 1. |
| c2 | key 2. |
References nsec3_cached_hash::dname, nsec3_cached_hash::nsec3, nsec3_get_algo(), nsec3_get_iter(), nsec3_get_salt(), query_dname_compare(), and nsec3_cached_hash::rr.
Referenced by fptr_whitelist_rbtree_cmp(), nsec3_cache_table_init(), and nsec3_hash_test().
| int nsec3_cache_table_init | ( | struct nsec3_cache_table * | ct, |
| struct regional * | region | ||
| ) |
Initialise the NSEC3 cache table.
| ct | the nsec3 cache table. |
| region | the region where allocations for the table will happen. |
References nsec3_hash_cmp(), rbtree_init(), and regional_alloc().
Referenced by ds_response_to_ke(), validate_any_response(), validate_cname_noanswer_response(), validate_cname_response(), validate_nameerror_response(), validate_nodata_response(), and validate_positive_response().
| int nsec3_hash_name | ( | rbtree_type * | table, |
| struct regional * | region, | ||
| struct sldns_buffer * | buf, | ||
| struct ub_packed_rrset_key * | nsec3, | ||
| int | rr, | ||
| uint8_t * | dname, | ||
| size_t | dname_len, | ||
| struct nsec3_cached_hash ** | hash | ||
| ) |
Obtain the hash of an owner name.
Used internally by the nsec3 proof functions in this file. published to enable unit testing of hash algorithms and cache.
| table | the cache table. Must be initialised at start. |
| region | scratch region to use for allocation. This region holds the tree, if you wipe the region, reinit the tree. |
| buf | temporary buffer. |
| nsec3 | the rrset with parameters |
| rr | rr number from d that has the NSEC3 parameters to hash to. |
| dname | name to hash This pointer is used inside the tree, assumed region-alloced. |
| dname_len | the length of the name. |
| hash | the hash node is returned on success. |
References nsec3_cached_hash::dname, nsec3_cached_hash::dname_len, nsec3_cached_hash::hash, rbnode_type::key, log_assert, nsec3_cached_hash::node, nsec3_cached_hash::nsec3, nsec3_calc_b32(), nsec3_calc_hash(), rbtree_insert(), rbtree_search(), regional_alloc(), and nsec3_cached_hash::rr.
Referenced by find_covering_nsec3(), find_matching_nsec3(), and nsec3_hash_test_entry().
| size_t nsec3_get_nextowner_b32 | ( | struct ub_packed_rrset_key * | rrset, |
| int | r, | ||
| uint8_t * | buf, | ||
| size_t | max | ||
| ) |
Get next owner name, converted to base32 encoding and with the zone name (taken from the nsec3 owner name) appended.
| rrset | the NSEC3 rrset. |
| r | the rr num of the nsec3 in the rrset. |
| buf | buffer to store name in |
| max | size of buffer. |
References packed_rrset_key::dname, packed_rrset_key::dname_len, dname_remove_label(), nsec3_get_nextowner(), nsec3_hash_to_b32(), and ub_packed_rrset_key::rk.
Referenced by wipeout().
| size_t nsec3_hash_to_b32 | ( | uint8_t * | hash, |
| size_t | hashlen, | ||
| uint8_t * | zone, | ||
| size_t | zonelen, | ||
| uint8_t * | buf, | ||
| size_t | max | ||
| ) |
Convert hash into base32 encoding and with the zone name appended.
| hash | hashed buffer |
| hashlen | length of hash |
| zone | name of zone |
| zonelen | length of zonename. |
| buf | buffer to store name in |
| max | size of buffer. |
References sldns_b32_ntop_extended_hex().
Referenced by neg_find_nsec3_ce(), neg_nsec3_getnc(), and nsec3_get_nextowner_b32().
| int nsec3_get_params | ( | struct ub_packed_rrset_key * | rrset, |
| int | r, | ||
| int * | algo, | ||
| size_t * | iter, | ||
| uint8_t ** | salt, | ||
| size_t * | saltlen | ||
| ) |
Get NSEC3 parameters out of rr.
| rrset | the NSEC3 rrset. |
| r | the rr num of the nsec3 in the rrset. |
| algo | nsec3 hash algo. |
| iter | iteration count. |
| salt | ptr to salt inside rdata. |
| saltlen | length of salt. |
References nsec3_get_algo(), nsec3_get_iter(), nsec3_get_salt(), nsec3_known_algo(), and nsec3_unknown_flags().
Referenced by neg_insert_data(), neg_params_ok(), and nsec3_of_param_has_type().
| size_t nsec3_get_hashed | ( | struct sldns_buffer * | buf, |
| uint8_t * | nm, | ||
| size_t | nmlen, | ||
| int | algo, | ||
| size_t | iter, | ||
| uint8_t * | salt, | ||
| size_t | saltlen, | ||
| uint8_t * | res, | ||
| size_t | max | ||
| ) |
Get NSEC3 hashed in a buffer.
| buf | buffer for temp use. |
| nm | name to hash |
| nmlen | length of nm. |
| algo | algo to use, must be known. |
| iter | iterations |
| salt | salt for nsec3 |
| saltlen | length of salt. |
| res | result of hash stored here. |
| max | maximum space for result. |
References nsec3_cached_hash::hash_len, log_err(), nsec3_hash_algo_size_supported(), query_dname_tolower(), secalgo_nsec3_hash(), sldns_buffer_begin(), sldns_buffer_clear(), sldns_buffer_flip(), sldns_buffer_limit(), and sldns_buffer_write().
Referenced by neg_find_nsec3_ce().
| int nsec3_has_type | ( | struct ub_packed_rrset_key * | rrset, |
| int | r, | ||
| uint16_t | type | ||
| ) |
see if NSEC3 RR contains given type
| rrset | NSEC3 rrset |
| r | RR in rrset |
| type | in host order to check bit for. |
References packed_rrset_data::count, lruhash_entry::data, ub_packed_rrset_key::entry, log_assert, nsecbitmap_has_type_rdata(), packed_rrset_data::rr_data, and packed_rrset_data::rr_len.
Referenced by neg_nsec3_proof_ds(), nsec3_do_prove_nodata(), nsec3_no_type(), nsec3_of_param_has_type(), nsec3_prove_closest_encloser(), and nsec3_prove_nods().
| int nsec3_has_optout | ( | struct ub_packed_rrset_key * | rrset, |
| int | r | ||
| ) |
return if nsec3 RR has the optout flag
| rrset | NSEC3 rrset |
| r | RR in rrset |
References packed_rrset_data::count, lruhash_entry::data, ub_packed_rrset_key::entry, log_assert, NSEC3_OPTOUT, packed_rrset_data::rr_data, and packed_rrset_data::rr_len.
Referenced by neg_nsec3_proof_ds(), nsec3_do_prove_nameerror(), nsec3_do_prove_nodata(), nsec3_prove_nods(), and nsec3_prove_wildcard().
| int nsec3_get_nextowner | ( | struct ub_packed_rrset_key * | rrset, |
| int | r, | ||
| uint8_t ** | next, | ||
| size_t * | nextlen | ||
| ) |
Return nsec3 RR next hashed owner name.
| rrset | NSEC3 rrset |
| r | RR in rrset |
| next | ptr into rdata to next owner hash |
| nextlen | length of hash. |
References packed_rrset_data::count, lruhash_entry::data, ub_packed_rrset_key::entry, log_assert, packed_rrset_data::rr_data, and packed_rrset_data::rr_len.
Referenced by nsec3_covers(), and nsec3_get_nextowner_b32().
| int nsec3_covers | ( | uint8_t * | zone, |
| struct nsec3_cached_hash * | hash, | ||
| struct ub_packed_rrset_key * | rrset, | ||
| int | rr, | ||
| struct sldns_buffer * | buf | ||
| ) |
nsec3Covers Given a hash and a candidate NSEC3Record, determine if that NSEC3Record covers the hash.
Covers specifically means that the hash is in between the owner and next hashes and does not equal either.
| zone | the zone name. |
| hash | the hash of the name |
| rrset | the rrset of the NSEC3. |
| rr | which rr in the rrset. |
| buf | temporary buffer. |
References packed_rrset_key::dname, nsec3_cached_hash::hash, label_compare_lower(), nsec3_get_nextowner(), query_dname_compare(), ub_packed_rrset_key::rk, nsec3_cached_hash::rr, sldns_b32_pton_extended_hex(), sldns_buffer_begin(), sldns_buffer_clear(), and sldns_buffer_limit().
Referenced by find_covering_nsec3(), and neg_nsec3_proof_ds().