/* * Copyright (C) Internet Systems Consortium, Inc. ("ISC") * * SPDX-License-Identifier: MPL-2.0 * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, you can obtain one at https://mozilla.org/MPL/2.0/. * * See the COPYRIGHT file distributed with this work for additional * information regarding copyright ownership. */ #pragma once /***** ***** Module Info *****/ /*! \file dns/validator.h * * \brief * DNS Validator * This is the BIND 9 validator, the module responsible for validating the * rdatasets and negative responses (messages). It makes use of zones in * the view and may fetch RRset to complete trust chains. It implements * DNSSEC as specified in RFC 4033, 4034 and 4035. * * Correct operation is critical to preventing spoofed answers from secure * zones being accepted. * * MP: *\li The module ensures appropriate synchronization of data structures it * creates and manipulates. * * Reliability: *\li No anticipated impact. * * Resources: *\li TBS * * Security: *\li No anticipated impact. * * Standards: *\li RFCs: 1034, 1035, 2181, 4033, 4034, 4035. */ #include #include #include #include #include #include #include #include #include /* for dns_rdata_rrsig_t */ #include #include #include #define DNS_VALIDATOR_NOQNAMEPROOF 0 #define DNS_VALIDATOR_NODATAPROOF 1 #define DNS_VALIDATOR_NOWILDCARDPROOF 2 #define DNS_VALIDATOR_CLOSESTENCLOSER 3 /*% * A validator object represents a validation in progress. * \brief * Clients are strongly discouraged from using this type directly, with * the exception of the 'link' field, which may be used directly for * whatever purpose the client desires. */ struct dns_validator { unsigned int magic; dns_view_t *view; isc_loop_t *loop; uint32_t tid; isc_refcount_t references; /* Name and type of the response to be validated. */ dns_name_t *name; dns_rdatatype_t type; /* * Callback and argument to use to inform the caller * that validation is complete. */ isc_job_cb cb; void *arg; /* Validation options (_DEFER, _NONTA, etc). */ unsigned int options; /* * Results of a completed validation. */ isc_result_t result; /* * Rdata and RRSIG (if any) for positive responses. */ dns_rdataset_t *rdataset; dns_rdataset_t *sigrdataset; /* * The full response. Required for negative responses. * Also required for positive wildcard responses. */ dns_message_t *message; /* * Proofs to be cached. */ dns_name_t *proofs[4]; /* * The denial type (NSEC or NSEC3) of the NOQNAME proof. */ dns_rdatatype_t noqnametype; /* * Optout proof seen. */ bool optout; /* * Answer is secure. */ bool secure; /* Internal validator state */ atomic_bool canceling; unsigned int attributes; isc_work_t *offloaded_work; isc_work_cb offloaded_cb; dns_fetch_t *fetch; dns_validator_t *subvalidator; dns_validator_t *parent; dns_keytable_t *keytable; dst_key_t *key; dns_rdata_rrsig_t *siginfo; unsigned int labels; dns_rdataset_t *nxset; dns_rdataset_t *keyset; dns_rdataset_t *dsset; dns_rdataset_t fdsset; dns_rdataset_t frdataset; dns_rdataset_t fsigrdataset; dns_fixedname_t fname; dns_fixedname_t wild; dns_fixedname_t wildsigner; dns_fixedname_t nseczone; dns_fixedname_t closest; ISC_LINK(dns_validator_t) link; bool mustbesecure; unsigned int depth; unsigned int authcount; unsigned int authfail; isc_stdtime_t start; bool resume; bool digest_sha1; uint8_t unsupported_algorithm; uint8_t unsupported_digest; uint16_t matchds_attempts; uint16_t validation_attempts; dns_rdata_t rdata; isc_counter_t *nvalidations; isc_counter_t *nfails; isc_counter_t *qc; isc_counter_t *gqc; fetchctx_t *parent_fetch; dns_edectx_t edectx; dns_edectx_t *cb_edectx; }; /*% * dns_validator_create() options. */ /* obsolete: #define DNS_VALIDATOR_DLV 0x0001U */ #define DNS_VALIDATOR_DEFER 0x0002U #define DNS_VALIDATOR_NOCDFLAG 0x0004U #define DNS_VALIDATOR_NONTA 0x0008U /*% Ignore NTA table */ ISC_LANG_BEGINDECLS isc_result_t dns_validator_create(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type, dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset, dns_message_t *message, unsigned int options, isc_loop_t *loop, isc_job_cb cb, void *arg, isc_counter_t *nvalidations, isc_counter_t *nfails, isc_counter_t *qc, isc_counter_t *gqc, fetchctx_t *parent, dns_edectx_t *edectx, dns_validator_t **validatorp); /*%< * Start a DNSSEC validation. * * On success (which is guaranteed as long as the view has valid * trust anchors), `validatorp` is updated to point to the new * validator. The caller is responsible for detaching it. * * The validator will validate a response to the question given by * 'name' and 'type'. * * To validate a positive response, the response data is * given by 'rdataset' and 'sigrdataset'. If 'sigrdataset' * is NULL, the data is presumed insecure and an attempt * is made to prove its insecurity by finding the appropriate * null key. * * The complete response message may be given in 'message', * to make available any authority section NSECs that may be * needed for validation of a response resulting from a * wildcard expansion (though no such wildcard validation * is implemented yet). If the complete response message * is not available, 'message' is NULL. * * To validate a negative response, the complete negative response * message is given in 'message'. The 'rdataset', and * 'sigrdataset' arguments must be NULL, but the 'name' and 'type' * arguments must be provided. * * The validation is performed in the context of 'view'. * * When the validation finishes, the callback function 'cb' is * called, passing a dns_valstatus_t object which contains a * poiner to 'arg'. The caller is responsible for freeing this * object. * * Its 'result' field will be ISC_R_SUCCESS iff the * response was successfully proven to be either secure or * part of a known insecure domain. */ void dns_validator_send(dns_validator_t *validator); /*%< * Send a deferred validation request * * Requires: * 'validator' to points to a valid DNSSEC validator. */ void dns_validator_cancel(dns_validator_t *validator); /*%< * Cancel a DNSSEC validation in progress. * * Requires: *\li 'validator' points to a valid DNSSEC validator, which * may or may not already have completed. * * Ensures: *\li It the validator has not already sent its completion * event, it will send it with result code ISC_R_CANCELED. */ void dns_validator_shutdown(dns_validator_t *val); /*%< * Release the name associated with the DNSSEC validator. * * Requires: * \li 'val' points to a valid DNSSEC validator. * \li The validator must have completed and sent its completion * event. * * Ensures: *\li The name associated with the DNSSEC validator is released. */ #if DNS_VALIDATOR_TRACE #define dns_validator_ref(ptr) \ dns_validator__ref(ptr, __func__, __FILE__, __LINE__) #define dns_validator_unref(ptr) \ dns_validator__unref(ptr, __func__, __FILE__, __LINE__) #define dns_validator_attach(ptr, ptrp) \ dns_validator__attach(ptr, ptrp, __func__, __FILE__, __LINE__) #define dns_validator_detach(ptrp) \ dns_validator__detach(ptrp, __func__, __FILE__, __LINE__) ISC_REFCOUNT_TRACE_DECL(dns_validator); #else ISC_REFCOUNT_DECL(dns_validator); #endif ISC_LANG_ENDDECLS