Functions
val_nsec.c File Reference

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

#include "config.h"
#include "validator/val_nsec.h"
#include "validator/val_utils.h"
#include "util/data/msgreply.h"
#include "util/data/dname.h"
#include "util/net_help.h"
#include "util/module.h"
#include "services/cache/rrset.h"

Functions

static uint32_t rrset_get_ttl (struct ub_packed_rrset_key *k)
 get ttl of rrset
 
int nsecbitmap_has_type_rdata (uint8_t *bitmap, size_t len, uint16_t type)
 nsec typemap check, takes an NSEC-type bitmap as argument, checks for type. More...
 
int nsec_has_type (struct ub_packed_rrset_key *nsec, uint16_t type)
 Check if type is present in the NSEC typemap. More...
 
static int nsec_get_next (struct ub_packed_rrset_key *nsec, uint8_t **nm, size_t *ln)
 Get next owner name from nsec record. More...
 
static enum sec_status val_nsec_proves_no_ds (struct ub_packed_rrset_key *nsec, struct query_info *qinfo)
 For an NSEC that matches the DS queried for, check absence of DS type. More...
 
static int nsec_verify_rrset (struct module_env *env, struct val_env *ve, struct ub_packed_rrset_key *nsec, struct key_entry_key *kkey, char **reason)
 check security status from cache or verify rrset, returns true if secure
 
enum sec_status val_nsec_prove_nodata_dsreply (struct module_env *env, struct val_env *ve, struct query_info *qinfo, struct reply_info *rep, struct key_entry_key *kkey, time_t *proof_ttl, char **reason)
 Check DS absence. More...
 
int nsec_proves_nodata (struct ub_packed_rrset_key *nsec, struct query_info *qinfo, uint8_t **wc)
 Determine if a NSEC proves the NOERROR/NODATA conditions. More...
 
int val_nsec_proves_name_error (struct ub_packed_rrset_key *nsec, uint8_t *qname)
 Determine if the given NSEC proves a NameError (NXDOMAIN) for a given qname. More...
 
int val_nsec_proves_insecuredelegation (struct ub_packed_rrset_key *nsec, struct query_info *qinfo)
 Determine if an nsec proves an insecure delegation towards the qname. More...
 
uint8_t * nsec_closest_encloser (uint8_t *qname, struct ub_packed_rrset_key *nsec)
 Determine closest encloser of a query name and the NSEC that covers it (and thus disproved it). More...
 
int val_nsec_proves_positive_wildcard (struct ub_packed_rrset_key *nsec, struct query_info *qinf, uint8_t *wc)
 Determine if the given NSEC proves a positive wildcard response. More...
 
int val_nsec_proves_no_wc (struct ub_packed_rrset_key *nsec, uint8_t *qname, size_t qnamelen)
 Determine if the given NSEC proves that a wildcard match does not exist. More...
 
static void dlv_topdomain (struct ub_packed_rrset_key *nsec, uint8_t *qname, uint8_t **nm, size_t *nm_len)
 Find shared topdomain that exists.
 
int val_nsec_check_dlv (struct query_info *qinfo, struct reply_info *rep, uint8_t **nm, size_t *nm_len)
 Determine the DLV result, what to do with NSEC DLV reply. More...
 

Detailed Description

This file contains helper functions for the validator module.

The functions help with NSEC checking, the different NSEC proofs for denial of existence, and proofs for presence of types.

Function Documentation

◆ nsecbitmap_has_type_rdata()

int nsecbitmap_has_type_rdata ( uint8_t *  bitmap,
size_t  len,
uint16_t  type 
)

nsec typemap check, takes an NSEC-type bitmap as argument, checks for type.

Parameters
bitmappointer to the bitmap part of wireformat rdata.
lenlength of the bitmap, in bytes.
typethe type (in host order) to check for.
Returns
true if the type bit was set in the bitmap. false if not, or if the bitmap was malformed in some way.

Referenced by nsec3_has_type(), nsec_has_type(), and unitest_nsec_has_type_rdata().

◆ nsec_has_type()

int nsec_has_type ( struct ub_packed_rrset_key nsec,
uint16_t  type 
)

Check if type is present in the NSEC typemap.

Parameters
nsecthe nsec RRset. If there are multiple RRs, then each must have the same typemap, since the typemap represents the types at this domain node.
typetype to check for, host order.
Returns
true if present

References packed_rrset_data::count, dname_valid(), nsecbitmap_has_type_rdata(), packed_rrset_data::rr_data, and packed_rrset_data::rr_len.

Referenced by nsec_proves_nodata(), val_nsec_proves_insecuredelegation(), and val_nsec_proves_name_error().

◆ nsec_get_next()

static int nsec_get_next ( struct ub_packed_rrset_key nsec,
uint8_t **  nm,
size_t *  ln 
)
static

Get next owner name from nsec record.

Parameters
nsecthe nsec RRset. If there are multiple RRs, then this will only return one of them.
nmthe next name is returned.
lnlength of nm is returned.
Returns
false on a bad NSEC RR (too short, malformed dname).

References packed_rrset_data::count, dname_valid(), packed_rrset_data::rr_data, and packed_rrset_data::rr_len.

Referenced by nsec_closest_encloser(), nsec_proves_nodata(), and val_nsec_proves_name_error().

◆ val_nsec_proves_no_ds()

static enum sec_status val_nsec_proves_no_ds ( struct ub_packed_rrset_key nsec,
struct query_info qinfo 
)
static

For an NSEC that matches the DS queried for, check absence of DS type.

Parameters
nsecNSEC for proof, must be trusted.
qinfowhat is queried for.
Returns
if secure the nsec proves that no DS is present, or insecure if it proves it is not a delegation point. or bogus if something was wrong.

References LDNS_RR_TYPE_DS, log_assert, query_info::qtype, ub_packed_rrset_key::rk, and packed_rrset_key::type.

◆ val_nsec_prove_nodata_dsreply()

enum sec_status val_nsec_prove_nodata_dsreply ( struct module_env env,
struct val_env ve,
struct query_info qinfo,
struct reply_info rep,
struct key_entry_key kkey,
time_t *  proof_ttl,
char **  reason 
)

Check DS absence.

There is a NODATA reply to a DS that needs checking. NSECs can prove this is not a delegation point, or successfully prove that there is no DS. Or this fails.

Parameters
envmodule env for rrsig verification routines.
vevalidator env for rrsig verification routines.
qinfothe DS queried for.
repreply received.
kkeykey entry to use for verification of signatures.
proof_ttlif secure, the TTL of how long this proof lasts.
reasonstring explaining why bogus.
Returns
security status. SECURE: proved absence of DS. INSECURE: proved that this was not a delegation point. BOGUS: crypto bad, or no absence of DS proven. UNCHECKED: there was no way to prove anything (no NSECs, unknown algo).

References query_info::qname, query_info::qname_len, and reply_find_rrset_section_ns().

◆ nsec_proves_nodata()

int nsec_proves_nodata ( struct ub_packed_rrset_key nsec,
struct query_info qinfo,
uint8_t **  wc 
)

Determine if a NSEC proves the NOERROR/NODATA conditions.

This will also handle the empty non-terminal (ENT) case and partially handle the wildcard case. If the ownername of 'nsec' is a wildcard, the validator must still be provided proof that qname did not directly exist and that the wildcard is, in fact, *.closest_encloser.

Parameters
nsecthe nsec record to check against.
qinfothe query info.
wcif the nodata is proven for a wildcard match, the wildcard closest encloser is returned, else NULL (wc is unchanged). This closest encloser must then match the nameerror given for the nextcloser of qname.
Returns
true if NSEC proves this.

References packed_rrset_key::dname, dname_canonical_compare(), dname_is_root(), dname_is_wild(), packed_rrset_key::dname_len, dname_remove_label(), dname_strict_subdomain_c(), dname_subdomain_c(), LDNS_RR_TYPE_CNAME, LDNS_RR_TYPE_DS, LDNS_RR_TYPE_NS, LDNS_RR_TYPE_SOA, log_assert, nsec_get_next(), nsec_has_type(), query_info::qname, query_info::qtype, query_dname_compare(), and ub_packed_rrset_key::rk.

◆ val_nsec_proves_name_error()

int val_nsec_proves_name_error ( struct ub_packed_rrset_key nsec,
uint8_t *  qname 
)

Determine if the given NSEC proves a NameError (NXDOMAIN) for a given qname.

Parameters
nsecthe nsec to check
qnamewhat was queried.
Returns
true if proven.

References packed_rrset_key::dname, dname_canonical_compare(), dname_strict_subdomain_c(), dname_subdomain_c(), LDNS_RR_TYPE_DNAME, LDNS_RR_TYPE_NS, LDNS_RR_TYPE_SOA, nsec_get_next(), nsec_has_type(), query_dname_compare(), and ub_packed_rrset_key::rk.

Referenced by val_nsec_proves_no_wc(), and val_nsec_proves_positive_wildcard().

◆ val_nsec_proves_insecuredelegation()

int val_nsec_proves_insecuredelegation ( struct ub_packed_rrset_key nsec,
struct query_info qinfo 
)

Determine if an nsec proves an insecure delegation towards the qname.

Parameters
nsecnsec rrset.
qinfowhat was queries for.
Returns
0 if not, 1 if an NSEC that signals an insecure delegation to the qname.

References packed_rrset_key::dname, dname_strict_subdomain_c(), dname_subdomain_c(), LDNS_RR_TYPE_DS, LDNS_RR_TYPE_NS, LDNS_RR_TYPE_SOA, nsec_has_type(), query_info::qname, query_info::qtype, and ub_packed_rrset_key::rk.

◆ nsec_closest_encloser()

uint8_t* nsec_closest_encloser ( uint8_t *  qname,
struct ub_packed_rrset_key nsec 
)

Determine closest encloser of a query name and the NSEC that covers it (and thus disproved it).

A name error must have been proven already, otherwise this will be invalid.

Parameters
qnamethe name queried for.
nsecthe nsec RRset.
Returns
closest encloser dname or NULL on error (bad nsec RRset).

References packed_rrset_key::dname, dname_count_labels(), dname_get_shared_topdomain(), nsec_get_next(), and ub_packed_rrset_key::rk.

Referenced by val_nsec_proves_no_wc(), and val_nsec_proves_positive_wildcard().

◆ val_nsec_proves_positive_wildcard()

int val_nsec_proves_positive_wildcard ( struct ub_packed_rrset_key nsec,
struct query_info qinf,
uint8_t *  wc 
)

Determine if the given NSEC proves a positive wildcard response.

Parameters
nsecthe nsec to check
qinfwhat was queried.
wcwildcard (without *. label)
Returns
true if proven.

References nsec_closest_encloser(), query_info::qname, query_dname_compare(), and val_nsec_proves_name_error().

◆ val_nsec_proves_no_wc()

int val_nsec_proves_no_wc ( struct ub_packed_rrset_key nsec,
uint8_t *  qname,
size_t  qnamelen 
)

Determine if the given NSEC proves that a wildcard match does not exist.

Parameters
nsecthe nsec RRset.
qnamethe name queried for.
qnamelenlength of qname.
Returns
true if proven.

References dname_count_labels(), dname_remove_labels(), LDNS_MAX_DOMAINLEN, nsec_closest_encloser(), and val_nsec_proves_name_error().

◆ val_nsec_check_dlv()

int val_nsec_check_dlv ( struct query_info qinfo,
struct reply_info rep,
uint8_t **  nm,
size_t *  nm_len 
)

Determine the DLV result, what to do with NSEC DLV reply.

Parameters
qinfowhat was queried for.
repthe nonpositive reply.
nmdlv lookup name, to adjust for new lookup name (if needed).
nm_lenlength of lookup name.
Returns
0 on error, 1 if a higher point is found. If the higher point is above the dlv repo anchor, the qname does not exist.

References reply_info::an_numrrsets, reply_info::flags, and FLAGS_GET_RCODE.