unbound: validator/val_nsec3.c File Reference

unbound 0.1

Data Structures | Functions
val_nsec3.c File Reference

This file contains helper functions for the validator module. More...

`#include "config.h"`
`#include <ctype.h>`
`#include "validator/val_nsec3.h"`
`#include "validator/val_secalgo.h"`
`#include "validator/validator.h"`
`#include "validator/val_kentry.h"`
`#include "services/cache/rrset.h"`
`#include "util/regional.h"`
`#include "util/rbtree.h"`
`#include "util/module.h"`
`#include "util/net_help.h"`
`#include "util/data/packed_rrset.h"`
`#include "util/data/dname.h"`
`#include "util/data/msgreply.h"`
`#include "validator/val_nsec.h"`
`#include "sldns/sbuffer.h"`

## Data Structures
struct | ce_response
| Closest encloser (ce) proof results Contains the ce and the next-closer (nc) proof. More...
struct | nsec3_filter
| Filter conditions for NSEC3 proof Used to iterate over the applicable NSEC3 RRs. More...

## Functions
int | sldns_b32_ntop_extended_hex (uint8_t const *src, size_t srclength, char *target, size_t targsize)
| This function we get from ldns-compat or from base system it returns the number of data bytes stored at the target, or <0 on error.
int | sldns_b32_pton_extended_hex (char const *src, size_t hashed_owner_str_len, uint8_t *target, size_t targsize)
| This function we get from ldns-compat or from base system it returns the number of data bytes stored at the target, or <0 on error.
static size_t | rrset_get_count (struct ub_packed_rrset_key *rrset)
| return number of rrs in an rrset
static int | nsec3_unknown_flags (struct ub_packed_rrset_key *rrset, int r)
| return if nsec3 RR has unknown flags
int | nsec3_has_optout (struct ub_packed_rrset_key *rrset, int r)
| return if nsec3 RR has the optout flag
static int | nsec3_get_algo (struct ub_packed_rrset_key *rrset, int r)
| return nsec3 RR algorithm
static int | nsec3_known_algo (struct ub_packed_rrset_key *rrset, int r)
| return if nsec3 RR has known algorithm
static size_t | nsec3_get_iter (struct ub_packed_rrset_key *rrset, int r)
| return nsec3 RR iteration count
static int | nsec3_get_salt (struct ub_packed_rrset_key *rrset, int r, uint8_t **salt, size_t *saltlen)
| return nsec3 RR salt
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.
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.
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.
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.
int | nsec3_has_type (struct ub_packed_rrset_key *rrset, int r, uint16_t type)
| see if NSEC3 RR contains given type
static struct ub_packed_rrset_key * | filter_next (struct nsec3_filter *filter, size_t *rrsetnum, int *rrnum)
| Iterate through NSEC3 list, per RR This routine gives the next RR in the list (or sets rrset null).
static struct ub_packed_rrset_key * | filter_first (struct nsec3_filter *filter, size_t *rrsetnum, int *rrnum)
| Start iterating over NSEC3 records.
static int | nsec3_rrset_has_known (struct ub_packed_rrset_key *s)
| see if at least one RR is known (flags, algo)
static void | filter_init (struct nsec3_filter *filter, struct ub_packed_rrset_key **list, size_t num, struct query_info *qinfo)
| Initialize the filter structure.
static size_t | get_max_iter (struct val_env *ve, size_t bits)
| Find max iteration count using config settings and key size.
static int | nsec3_iteration_count_high (struct val_env *ve, struct nsec3_filter *filter, struct key_entry_key *kkey)
| Determine if any of the NSEC3 rrs iteration count is too high, from key.
int | nsec3_hash_cmp (const void *c1, const void *c2)
| Rbtree for hash cache comparison function.
size_t | nsec3_get_hashed (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.
static int | nsec3_calc_hash (struct regional *region, sldns_buffer *buf, struct nsec3_cached_hash *c)
| perform hash of name
static int | nsec3_calc_b32 (struct regional *region, sldns_buffer *buf, struct nsec3_cached_hash *c)
| perform b32 encoding of hash
int | nsec3_hash_name (rbtree_type *table, struct regional *region, 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.
static int | label_compare_lower (uint8_t *lab1, uint8_t *lab2, size_t lablen)
| compare a label lowercased
static int | nsec3_hash_matches_owner (struct nsec3_filter *flt, struct nsec3_cached_hash *hash, struct ub_packed_rrset_key *s)
| Compare a hashed name with the owner name of an NSEC3 RRset.
static int | find_matching_nsec3 (struct module_env *env, struct nsec3_filter *flt, rbtree_type *ct, uint8_t *nm, size_t nmlen, struct ub_packed_rrset_key **rrset, int *rr)
| Find matching NSEC3 Find the NSEC3Record that matches a hash of a name.
int | nsec3_covers (uint8_t *zone, struct nsec3_cached_hash *hash, struct ub_packed_rrset_key *rrset, int rr, sldns_buffer *buf)
| nsec3Covers Given a hash and a candidate NSEC3Record, determine if that NSEC3Record covers the hash.
static int | find_covering_nsec3 (struct module_env *env, struct nsec3_filter *flt, rbtree_type *ct, uint8_t *nm, size_t nmlen, struct ub_packed_rrset_key **rrset, int *rr)
| findCoveringNSEC3 Given a name, find a covering NSEC3 from among a list of NSEC3s.
static int | nsec3_find_closest_encloser (struct module_env *env, struct nsec3_filter *flt, rbtree_type *ct, struct query_info *qinfo, struct ce_response *ce)
| findClosestEncloser Given a name and a list of NSEC3s, find the candidate closest encloser.
static void | next_closer (uint8_t *qname, size_t qnamelen, uint8_t *ce, uint8_t **nm, size_t *nmlen)
| Given a qname and its proven closest encloser, calculate the "next closest" name.
static enum sec_status | nsec3_prove_closest_encloser (struct module_env *env, struct nsec3_filter *flt, rbtree_type *ct, struct query_info *qinfo, int prove_does_not_exist, struct ce_response *ce)
| proveClosestEncloser Given a List of nsec3 RRs, find and prove the closest encloser to qname.
static uint8_t * | nsec3_ce_wildcard (struct regional *region, uint8_t *ce, size_t celen, size_t *len)
| allocate a wildcard for the closest encloser
static enum sec_status | nsec3_do_prove_nameerror (struct module_env *env, struct nsec3_filter *flt, rbtree_type *ct, struct query_info *qinfo)
| Do the name error proof.
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)
| Determine if the set of NSEC3 records provided with a response prove NAME ERROR.
static enum sec_status | nsec3_do_prove_nodata (struct module_env *env, struct nsec3_filter *flt, rbtree_type *ct, struct query_info *qinfo)
| Do the nodata proof.
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)
| 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)
| Prove that a positive wildcard match was appropriate (no direct match RRset).
static int | list_is_secure (struct module_env *env, struct val_env *ve, struct ub_packed_rrset_key **list, size_t num, struct key_entry_key *kkey, char **reason, sldns_ede_code *reason_bogus, struct module_qstate *qstate)
| test if list is all secure
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)
| 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)
| Prove NXDOMAIN or NODATA.

## Detailed Description

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.

## Function Documentation

## ◆ nsec3_has_optout()

int nsec3_has_optout | ( | struct ub_packed_rrset_key * | rrset,
|  | int | r
| ) |  |

return if nsec3 RR has the optout flag

Parameters

  rrset | NSEC3 rrset
  r | RR in rrset

Returns
  true if optout, false on error or not optout

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().

## ◆ nsec3_get_params()

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.

Parameters

  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.

Returns
  0 if bad formatted, unknown nsec3 hash algo, or unknown flags set.

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().

## ◆ nsec3_get_nextowner()

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.

Parameters

  rrset | NSEC3 rrset
  r | RR in rrset
  next | ptr into rdata to next owner hash
  nextlen | length of hash.

Returns
  false on malformed

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().

## ◆ nsec3_hash_to_b32()

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.

Parameters

  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.

Returns
  length of name on success. 0 on failure (buffer too short or bad format nsec3 record).

References sldns_b32_ntop_extended_hex().

Referenced by neg_find_nsec3_ce(), neg_nsec3_getnc(), and nsec3_get_nextowner_b32().

## ◆ nsec3_get_nextowner_b32()

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.

Parameters

  rrset | the NSEC3 rrset.
  r | the rr num of the nsec3 in the rrset.
  buf | buffer to store name in
  max | size of buffer.

Returns
  length of name on success. 0 on failure (buffer too short or bad format nsec3 record).

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().

## ◆ nsec3_has_type()

int nsec3_has_type | ( | struct ub_packed_rrset_key * | rrset,
|  | int | r,
|  | uint16_t | type
| ) |  |

see if NSEC3 RR contains given type

Parameters

  rrset | NSEC3 rrset
  r | RR in rrset
  type | in host order to check bit for.

Returns
  true if bit set, false if not or error.

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().

## ◆ filter_next()

static struct ub_packed_rrset_key * filter_next | ( | struct nsec3_filter * | filter,
|  | size_t * | rrsetnum,
|  | int * | rrnum
| ) |  |
| static

Iterate through NSEC3 list, per RR This routine gives the next RR in the list (or sets rrset null).

Usage:

size_t rrsetnum; int rrnum; struct ub_packed_rrset_key* rrset; for(rrset=filter_first(filter, &rrsetnum, &rrnum); rrset; rrset=filter_next(filter, &rrsetnum, &rrnum)) do_stuff;

Also filters out o unknown flag NSEC3s o unknown algorithm NSEC3s.

Parameters

  filter | nsec3 filter structure.
  rrsetnum | in/out rrset number to look at.
  rrnum | in/out rr number in rrset to look at.

Returns
  ptr to the next rrset (or NULL at end).

References packed_rrset_key::dname, packed_rrset_key::dname_len, dname_remove_label(), nsec3_filter::fclass, nsec3_filter::list, nsec3_known_algo(), nsec3_unknown_flags(), nsec3_filter::num, query_dname_compare(), ub_packed_rrset_key::rk, packed_rrset_key::rrset_class, rrset_get_count(), packed_rrset_key::type, and nsec3_filter::zone.

Referenced by filter_first(), find_covering_nsec3(), find_matching_nsec3(), and nsec3_iteration_count_high().

## ◆ filter_first()

static struct ub_packed_rrset_key * filter_first | ( | struct nsec3_filter * | filter,
|  | size_t * | rrsetnum,
|  | int * | rrnum
| ) |  |
| static

Start iterating over NSEC3 records.

Parameters

  filter | the filter structure, must have been filter_init-ed.
  rrsetnum | can be undefined on call, initialised.
  rrnum | can be undefined on call, initialised.

Returns
  first rrset of an NSEC3, together with rrnum this points to the first RR to examine. Is NULL on empty list.

References filter_next().

Referenced by find_covering_nsec3(), find_matching_nsec3(), and nsec3_iteration_count_high().

## ◆ filter_init()

static void filter_init | ( | struct nsec3_filter * | filter,
|  | struct ub_packed_rrset_key ** | list,
|  | size_t | num,
|  | struct query_info * | qinfo
| ) |  |
| static

Initialize the filter structure.

Finds the zone by looking at available NSEC3 records and best match. (skips the unknown flag and unknown algo NSEC3s).

Parameters

  filter | nsec3 filter structure.
  list | list of rrsets, an array of them.
  num | number of rrsets in list.
  qinfo | query name to match a zone for. query type (if DS a higher zone must be chosen) qclass, to filter NSEC3s with.

References packed_rrset_key::dname, dname_is_root(), packed_rrset_key::dname_len, dname_remove_label(), dname_subdomain_c(), nsec3_filter::fclass, LDNS_RR_TYPE_DS, nsec3_filter::list, nsec3_rrset_has_known(), nsec3_filter::num, query_info::qclass, query_info::qname, query_info::qtype, query_dname_compare(), ub_packed_rrset_key::rk, packed_rrset_key::rrset_class, packed_rrset_key::type, nsec3_filter::zone, and nsec3_filter::zone_len.

Referenced by nsec3_prove_nameerror(), nsec3_prove_nodata(), nsec3_prove_nods(), nsec3_prove_nxornodata(), and nsec3_prove_wildcard().

## ◆ get_max_iter()

static size_t get_max_iter | ( | struct val_env * | ve,
|  | size_t | bits
| ) |  |
| static

Find max iteration count using config settings and key size.

Parameters

  ve | validator environment with iteration count config settings.
  bits | key size

Returns
  max iteration count

References log_assert, val_env::nsec3_keyiter_count, and val_env::nsec3_maxiter.

Referenced by nsec3_iteration_count_high().

## ◆ nsec3_iteration_count_high()

static int nsec3_iteration_count_high | ( | struct val_env * | ve,
|  | struct nsec3_filter * | filter,
|  | struct key_entry_key * | kkey
| ) |  |
| static

Determine if any of the NSEC3 rrs iteration count is too high, from key.

Parameters

  ve | validator environment with iteration count config settings.
  filter | what NSEC3s to loop over.
  kkey | key entry used for verification; used for iteration counts.

Returns
  1 if some nsec3s are above the max iteration count.

References filter_first(), filter_next(), get_max_iter(), key_entry_keysize(), nsec3_get_iter(), VERB_ALGO, and verbose().

Referenced by nsec3_prove_nameerror(), nsec3_prove_nodata(), nsec3_prove_nods(), nsec3_prove_nxornodata(), and nsec3_prove_wildcard().

## ◆ nsec3_hash_cmp()

int nsec3_hash_cmp | ( | const void * | c1,
|  | const void * | c2
| ) |  |

Rbtree for hash cache comparison function.

Parameters

  c1 | key 1.
  c2 | key 2.

Returns
  : comparison code, -1, 0, 1, of the keys.

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_hash_test(), nsec3_prove_nameerror(), nsec3_prove_nodata(), nsec3_prove_nods(), nsec3_prove_nxornodata(), and nsec3_prove_wildcard().

## ◆ nsec3_get_hashed()

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.

Parameters

  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.

Returns
  0 on failure, otherwise bytelength stored.

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().

## ◆ nsec3_hash_name()

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.

Parameters

  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.

Returns
  : 1 on success, either from cache or newly hashed hash is returned. 0 on a malloc failure. -1 if the NSEC3 rr was badly formatted (i.e. formerr).

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().

## ◆ nsec3_hash_matches_owner()

static int nsec3_hash_matches_owner | ( | struct nsec3_filter * | flt,
|  | struct nsec3_cached_hash * | hash,
|  | struct ub_packed_rrset_key * | s
| ) |  |
| static

Compare a hashed name with the owner name of an NSEC3 RRset.

Parameters

  flt | filter with zone name.
  hash | the hashed name.
  s | rrset with owner name.

Returns
  true if matches exactly, false if not.

References packed_rrset_key::dname, nsec3_cached_hash::hash, label_compare_lower(), query_dname_compare(), ub_packed_rrset_key::rk, and nsec3_filter::zone.

Referenced by find_matching_nsec3().

## ◆ find_matching_nsec3()

static int find_matching_nsec3 | ( | struct module_env * | env,
|  | struct nsec3_filter * | flt,
|  | rbtree_type * | ct,
|  | uint8_t * | nm,
|  | size_t | nmlen,
|  | struct ub_packed_rrset_key ** | rrset,
|  | int * | rr
| ) |  |
| static

Find matching NSEC3 Find the NSEC3Record that matches a hash of a name.

Parameters

  env | module environment with temporary region and buffer.
  flt | the NSEC3 RR filter, contains zone name and RRs.
  ct | cached hashes table.
  nm | name to look for.
  nmlen | length of name.
  rrset | nsec3 that matches is returned here.
  rr | rr number in nsec3 rrset that matches.

Returns
  true if a matching NSEC3 is found, false if not.

References filter_first(), filter_next(), nsec3_cached_hash::hash, log_err(), nsec3_hash_matches_owner(), nsec3_hash_name(), nsec3_cached_hash::rr, module_env::scratch, and module_env::scratch_buffer.

Referenced by nsec3_do_prove_nodata(), nsec3_find_closest_encloser(), and nsec3_prove_nods().

## ◆ nsec3_covers()

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.

Parameters

  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.

Returns
  true if covers, false if not.

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().

## ◆ find_covering_nsec3()

static int find_covering_nsec3 | ( | struct module_env * | env,
|  | struct nsec3_filter * | flt,
|  | rbtree_type * | ct,
|  | uint8_t * | nm,
|  | size_t | nmlen,
|  | struct ub_packed_rrset_key ** | rrset,
|  | int * | rr
| ) |  |
| static

findCoveringNSEC3 Given a name, find a covering NSEC3 from among a list of NSEC3s.

Parameters

  env | module environment with temporary region and buffer.
  flt | the NSEC3 RR filter, contains zone name and RRs.
  ct | cached hashes table.
  nm | name to check if covered.
  nmlen | length of name.
  rrset | covering NSEC3 rrset is returned here.
  rr | rr of cover is returned here.

Returns
  true if a covering NSEC3 is found, false if not.

References filter_first(), filter_next(), nsec3_cached_hash::hash, log_err(), nsec3_covers(), nsec3_hash_name(), nsec3_cached_hash::rr, module_env::scratch, module_env::scratch_buffer, and nsec3_filter::zone.

Referenced by nsec3_do_prove_nameerror(), nsec3_prove_closest_encloser(), and nsec3_prove_wildcard().

## ◆ nsec3_find_closest_encloser()

static int nsec3_find_closest_encloser | ( | struct module_env * | env,
|  | struct nsec3_filter * | flt,
|  | rbtree_type * | ct,
|  | struct query_info * | qinfo,
|  | struct ce_response * | ce
| ) |  |
| static

findClosestEncloser Given a name and a list of NSEC3s, find the candidate closest encloser.

This will be the first ancestor of 'name' (including itself) to have a matching NSEC3 RR.

Parameters

  env | module environment with temporary region and buffer.
  flt | the NSEC3 RR filter, contains zone name and RRs.
  ct | cached hashes table.
  qinfo | query that is verified for.
  ce | closest encloser information is returned in here.

Returns
  true if a closest encloser candidate is found, false if not.

References ce_response::ce, ce_response::ce_len, ce_response::ce_rr, ce_response::ce_rrset, dname_remove_label(), dname_subdomain_c(), find_matching_nsec3(), query_info::qname, query_info::qname_len, and nsec3_filter::zone.

Referenced by nsec3_prove_closest_encloser().

## ◆ next_closer()

static void next_closer | ( | uint8_t * | qname,
|  | size_t | qnamelen,
|  | uint8_t * | ce,
|  | uint8_t ** | nm,
|  | size_t * | nmlen
| ) |  |
| static

Given a qname and its proven closest encloser, calculate the "next closest" name.

Basically, this is the name that is one label longer than the closest encloser that is still a subdomain of qname.

Parameters

  qname | query name.
  qnamelen | length of qname.
  ce | closest encloser
  nm | result name.
  nmlen | length of nm.

References dname_count_labels(), and dname_remove_labels().

Referenced by nsec3_prove_closest_encloser(), and nsec3_prove_wildcard().

## ◆ nsec3_prove_closest_encloser()

static enum sec_status nsec3_prove_closest_encloser | ( | struct module_env * | env,
|  | struct nsec3_filter * | flt,
|  | rbtree_type * | ct,
|  | struct query_info * | qinfo,
|  | int | prove_does_not_exist,
|  | struct ce_response * | ce
| ) |  |
| static

proveClosestEncloser Given a List of nsec3 RRs, find and prove the closest encloser to qname.

Parameters

  env | module environment with temporary region and buffer.
  flt | the NSEC3 RR filter, contains zone name and RRs.
  ct | cached hashes table.
  qinfo | query that is verified for.
  prove_does_not_exist | If true, then if the closest encloser turns out to be qname, then null is returned. If set true, and the return value is true, then you can be certain that the ce.nc_rrset and ce.nc_rr are set properly.
  ce | closest encloser information is returned in here.

Returns
  bogus if no closest encloser could be proven. secure if a closest encloser could be proven, ce is set. insecure if the closest-encloser candidate turns out to prove that an insecure delegation exists above the qname.

References ce_response::ce, ce_response::ce_rr, ce_response::ce_rrset, find_covering_nsec3(), LDNS_RR_TYPE_DNAME, LDNS_RR_TYPE_DS, LDNS_RR_TYPE_NS, LDNS_RR_TYPE_SOA, log_nametypeclass(), ce_response::nc_rr, ce_response::nc_rrset, next_closer(), nsec3_find_closest_encloser(), nsec3_has_type(), query_info::qname, query_info::qname_len, query_dname_compare(), sec_status_bogus, sec_status_insecure, sec_status_secure, VERB_ALGO, and verbose().

Referenced by nsec3_do_prove_nameerror(), nsec3_do_prove_nodata(), and nsec3_prove_nods().

## ◆ nsec3_prove_nameerror()

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
| ) |  |

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.

Parameters

  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.

Returns
  : sec_status SECURE of the Name Error is proven by the NSEC3 RRs, BOGUS if not, INSECURE if all of the NSEC3s could be validly ignored.

References filter_init(), key_entry_isgood(), nsec3_filter::list, log_nametypeclass(), nsec3_do_prove_nameerror(), nsec3_hash_cmp(), nsec3_iteration_count_high(), nsec3_filter::num, rbtree_init(), sec_status_bogus, sec_status_insecure, VERB_ALGO, and nsec3_filter::zone.

Referenced by validate_nameerror_response().

## ◆ nsec3_prove_nodata()

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
| ) |  |

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)

Parameters

  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.

Returns
  : sec_status SECURE of the proposition is proven by the NSEC3 RRs, BOGUS if not, INSECURE if all of the NSEC3s could be validly ignored.

References filter_init(), key_entry_isgood(), nsec3_filter::list, nsec3_do_prove_nodata(), nsec3_hash_cmp(), nsec3_iteration_count_high(), nsec3_filter::num, rbtree_init(), sec_status_bogus, sec_status_insecure, and nsec3_filter::zone.

Referenced by validate_nodata_response().

## ◆ nsec3_prove_wildcard()

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
| ) |  |

Prove that a positive wildcard match was appropriate (no direct match RRset).

Parameters

  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.

Returns
  : sec_status SECURE of the proposition is proven by the NSEC3 RRs, BOGUS if not, INSECURE if all of the NSEC3s could be validly ignored.

References ce_response::ce, dname_count_size_labels(), filter_init(), find_covering_nsec3(), key_entry_isgood(), next_closer(), nsec3_has_optout(), nsec3_hash_cmp(), nsec3_iteration_count_high(), query_info::qname, query_info::qname_len, rbtree_init(), sec_status_bogus, sec_status_insecure, sec_status_secure, VERB_ALGO, verbose(), and nsec3_filter::zone.

Referenced by validate_any_response(), validate_cname_response(), and validate_positive_response().

## ◆ nsec3_prove_nods()

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
| ) |  |

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.

Parameters

  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.

Returns
  : sec_status SECURE of the proposition is proven by the NSEC3 RRs, BOGUS if not, INSECURE if all of the NSEC3s could be validly ignored. or if there was no DS in an insecure (i.e., opt-in) way, INDETERMINATE if it was clear that this wasn't a delegation point.

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, ce_response::nc_rr, ce_response::nc_rrset, nsec3_has_optout(), nsec3_has_type(), nsec3_hash_cmp(), nsec3_iteration_count_high(), nsec3_prove_closest_encloser(), query_info::qname, query_info::qname_len, query_info::qtype, rbtree_init(), sec_status_bogus, sec_status_indeterminate, sec_status_insecure, sec_status_secure, VERB_ALGO, verbose(), and nsec3_filter::zone.

Referenced by ds_response_to_ke().

## ◆ nsec3_prove_nxornodata()

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
| ) |  |

Prove NXDOMAIN or NODATA.

Parameters

  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.

Returns
  : sec_status SECURE of the proposition is proven by the NSEC3 RRs, BOGUS if not, INSECURE if all of the NSEC3s could be validly ignored.

References filter_init(), key_entry_isgood(), nsec3_filter::list, nsec3_do_prove_nameerror(), nsec3_do_prove_nodata(), nsec3_hash_cmp(), nsec3_iteration_count_high(), nsec3_filter::num, rbtree_init(), sec_status_bogus, sec_status_insecure, sec_status_secure, and nsec3_filter::zone.

Referenced by validate_cname_noanswer_response().