From: haikuo zhang Date: Wed, 11 Apr 2012 15:30:29 +0000 (+0800) Subject: [1579] adjust codes for the flag in the find function. Using a helper class to X-Git-Tag: trac2351_base~226^2~116^2~41^2~19 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=4eeff0e79de122645ffd3bf117a1486147fc9541;p=thirdparty%2Fkea.git [1579] adjust codes for the flag in the find function. Using a helper class to deal with the flag. --- diff --git a/INSTALL b/INSTALL index 839f1207ca..945020ef7e 100644 --- a/INSTALL +++ b/INSTALL @@ -1,4 +1,4 @@ -If using git (not the tarball), build the "configure" file: +f using git (not the tarball), build the "configure" file: autoreconf --install To then build from source: diff --git a/src/lib/datasrc/database.cc b/src/lib/datasrc/database.cc index 748b562959..5ae00e7a6c 100644 --- a/src/lib/datasrc/database.cc +++ b/src/lib/datasrc/database.cc @@ -423,17 +423,9 @@ DatabaseClient::Finder::findAll(const isc::dns::Name& name, std::vector& target, const FindOptions options) { - const bool need_nsec3 = (((options & FIND_DNSSEC) != 0) && isNSEC3()); - if (need_nsec3 && isNSEC()) { - isc_throw(DataSourceError, "nsec and nsec3 coexist"); - } - // If the zone is signed with NSEC3, need to add RESULT_NSEC3_SIGNED to the - // flags in FindContext when NXRRSET NXDOMAIN or WILDCARD in the DNSSEC - // query, no need NSEC RRset at the same time. return (ZoneFinderContextPtr(new Context(*this, options, findInternal(name, RRType::ANY(), - &target, options, - need_nsec3), + &target, options), target))); } @@ -445,17 +437,9 @@ DatabaseClient::Finder::find(const isc::dns::Name& name, if (type == RRType::ANY()) { isc_throw(isc::Unexpected, "Use findAll to answer ANY"); } - // If the zone is signed with NSEC3, need to add RESULT_NSEC3_SIGNED to the - // flags in FindContext when NXRRSET NXDOMAIN or WILDCARD in the DNSSEC - // query, no need NSEC RRset at the same time. - const bool need_nsec3 = (((options & FIND_DNSSEC) != 0) && isNSEC3()); - if (need_nsec3 && isNSEC()) { - isc_throw(DataSourceError, "nsec and nsec3 coexist"); - } return (ZoneFinderContextPtr(new Context(*this, options, findInternal(name, type, NULL, - options, - need_nsec3)))); + options)))); } DatabaseClient::Finder::DelegationSearchResult @@ -617,15 +601,17 @@ DatabaseClient::Finder::findDelegationPoint(const isc::dns::Name& name, // // If none of the above applies in any level, the search fails with NXDOMAIN. ZoneFinder::ResultContext -DatabaseClient::Finder::findWildcardMatch( - const isc::dns::Name& name, const isc::dns::RRType& type, - const FindOptions options, const DelegationSearchResult& dresult, - std::vector* target, const bool need_nsec3) +DatabaseClient::Finder::findWildcardMatch(const isc::dns::Name& name, + const isc::dns::RRType& type, + const DelegationSearchResult& dresult, + std::vector* + target, FindDNSSECContext& dnssec_ctx) { // Note that during the search we are going to search not only for the // requested type, but also for types that indicate a delegation - // NS and DNAME. - WantedTypes final_types(need_nsec3 ? FINAL_TYPES_NO_NSEC() : FINAL_TYPES()); + WantedTypes final_types(dnssec_ctx.isNSEC3() ? FINAL_TYPES_NO_NSEC() : + FINAL_TYPES()); final_types.insert(type); const size_t remove_labels = name.getLabelCount() - dresult.last_known; @@ -647,7 +633,7 @@ DatabaseClient::Finder::findWildcardMatch( if (dresult.first_ns) { // About to use first_ns. The only way this can be set is if // we are searching for glue, so do a sanity check. - if ((options & FIND_GLUE_OK) == 0) { + if ((dnssec_ctx.getOptions() & FIND_GLUE_OK) == 0) { isc_throw(Unexpected, "Inconsistent conditions during " "cancel of wilcard search for " << name.toText() << ": find_ns non-null when not " @@ -663,8 +649,8 @@ DatabaseClient::Finder::findWildcardMatch( } else if (!hasSubdomains(name.split(i - 1).toText())) { // The wildcard match is the best one, find the final result // at it. Note that wildcard should never be the zone origin. - return (findOnNameResult(name, type, options, false, - found, &wildcard, target, need_nsec3)); + return (findOnNameResult(name, type, found, &wildcard, + target, dnssec_ctx)); } else { // more specified match found, cancel wildcard match @@ -680,17 +666,15 @@ DatabaseClient::Finder::findWildcardMatch( LOG_DEBUG(logger, DBG_TRACE_DETAILED, DATASRC_DATABASE_WILDCARD_EMPTY). arg(accessor_->getDBName()).arg(wildcard).arg(name); - if (((options & FIND_DNSSEC) != 0) && !need_nsec3) { + FindResultFlags flags = (RESULT_WILDCARD | + dnssec_ctx.getResultFlags()); + if (dnssec_ctx.isNSEC()) { ConstRRsetPtr nsec = findNSECCover(Name(wildcard)); if (nsec) { - return (ResultContext(NXRRSET, nsec, - RESULT_WILDCARD | - RESULT_NSEC_SIGNED)); + return (ResultContext(NXRRSET, nsec, flags)); } } - return (ResultContext(NXRRSET, ConstRRsetPtr(), need_nsec3 ? - (RESULT_WILDCARD | RESULT_NSEC3_SIGNED) : - RESULT_WILDCARD)); + return (ResultContext(NXRRSET, ConstRRsetPtr(), flags)); } } @@ -728,23 +712,157 @@ DatabaseClient::Finder::logAndCreateResult( return (ResultContext(code, rrset, flags)); } +DatabaseClient::Finder::FindDNSSECContext::FindDNSSECContext( + DatabaseClient::Finder* finderp, + const isc::datasrc::ZoneFinder::FindOptions options, + const Name& origin) : + finderp_(finderp), + options_(options), + origin_(origin), + initialized_(false) +{} + +ZoneFinder::FindOptions +DatabaseClient::Finder::FindDNSSECContext::getOptions() const +{ + return options_; +} + +void +DatabaseClient::Finder::FindDNSSECContext::init() +{ + if (finderp_ == NULL) { + isc_throw(DataSourceError, "no Finder to query"); + } + if (!initialized_) { + initialized_ = true; + // If NSEC3PARAM rrset exists, the zone looks like signed with NSEC3 + is_nsec3_ = ((options_ & FIND_DNSSEC) == 0) ? false : + finderp_->isNSEC3(); + if (is_nsec3_) { + // If the zone is signed with NSEC3, no need to check NSEC. If NSEC + // and NSEC3 coexist, according to RFC 5155 10-4, it should return + // result as NSEC3. + is_nsec_ = false; + } else { + // If no NSEC3PARAM and it is DNSSEC query, check whether NSEC + // exist in apex of zone + is_nsec_ = ((options_ & FIND_DNSSEC) == 0) ? false : + finderp_->isNSEC(); + } + } +} + +bool +DatabaseClient::Finder::FindDNSSECContext::isInited() +{ + return initialized_; +} + +bool +DatabaseClient::Finder::FindDNSSECContext::isNSEC3() +{ + if (isInited()) { + return is_nsec3_; + } else { + init(); + return is_nsec3_; + } +} + +bool +DatabaseClient::Finder::FindDNSSECContext::isNSEC() +{ + if (isInited()) { + return is_nsec_; + } else { + init(); + return is_nsec_; + } +} + +isc::dns::ConstRRsetPtr +DatabaseClient::Finder::FindDNSSECContext::getNSECRRset( + const FoundRRsets& found_set) const +{ + const FoundIterator nci = found_set.second.find(RRType::NSEC()); + if (nci != found_set.second.end()) { + return nci->second; + } else { + return ConstRRsetPtr(); + } +} + +isc::dns::ConstRRsetPtr +DatabaseClient::Finder::FindDNSSECContext::getNSECRRset(const Name &name) const +{ + if (finderp_ == NULL) { + isc_throw(DataSourceError, "no Finder to query"); + } + const FoundRRsets wfound = finderp_->getRRsets(name.toText(), NSEC_TYPES(), + true); + const FoundIterator nci = wfound.second.find(RRType::NSEC()); + if (nci != wfound.second.end()) { + return nci->second; + } else { + return ConstRRsetPtr(); + } +} + +DatabaseClient::Finder::FoundRRsets +DatabaseClient::Finder::FindDNSSECContext::getDNSSECRRset(const Name& name, + const RRType& type) +{ + if (finderp_ == NULL) { + isc_throw(DataSourceError, "no Finder to query"); + } + const bool is_origin = isOrigin(name); + bool is_nsec = isNSEC(); + WantedTypes final_types(is_nsec ? FINAL_TYPES() : FINAL_TYPES_NO_NSEC()); + final_types.insert(type); + return (finderp_->getRRsets(name.toText(), final_types, !is_origin, NULL, + type == RRType::ANY())); +} + +bool +DatabaseClient::Finder::FindDNSSECContext::isOrigin(const Name &name) const +{ + return (name == origin_); +} + +ZoneFinder::FindResultFlags +DatabaseClient::Finder::FindDNSSECContext::getResultFlags() +{ + // If it is not DNSSEC query, it should return RESULT_DEFAULT + if ((options_ & FIND_DNSSEC) == 0) { + return RESULT_DEFAULT; + } + // If it is a DNSSEC query and the zone is signed with NSEC3, it should + // return RESULT_NSEC3_SIGNED + if (isNSEC3()) { + return RESULT_NSEC3_SIGNED; + } else { + // If it is a DNSSEC query and the zone is signed with NSEC, it should + // return RESULT_NSEC_SIGNED, other else, return RESULT_DEFAULT + return (isNSEC() ? RESULT_NSEC_SIGNED : RESULT_DEFAULT); + } +} + ZoneFinder::ResultContext DatabaseClient::Finder::findOnNameResult(const Name& name, const RRType& type, - const FindOptions options, - const bool is_origin, const FoundRRsets& found, const string* wildname, std::vector* - target, const bool need_nsec3) + target, FindDNSSECContext& dnssec_ctx) { const bool wild = (wildname != NULL); - FindResultFlags flags; - if (need_nsec3) { - flags = wild ? (RESULT_WILDCARD | RESULT_NSEC3_SIGNED) : - RESULT_DEFAULT; - } else { - flags = wild ? RESULT_WILDCARD : RESULT_DEFAULT; + FindResultFlags flags = wild ? RESULT_WILDCARD : RESULT_DEFAULT; + // If the zone file is signed with NSEC3, need to set RESULT_NSEC3_SIGNED + // flag in the flags. It is good for upper caller to deal with the query + // response message. + if (wild & dnssec_ctx.isNSEC3()) { + flags = (flags | RESULT_NSEC3_SIGNED); } // Get iterators for the different types of records we are interested in - // CNAME, NS and Wanted types. @@ -754,15 +872,13 @@ DatabaseClient::Finder::findOnNameResult(const Name& name, // For wildcard case with DNSSEC required, the caller would need to know // whether it's NSEC or NSEC3 signed. So we need to do an additional // search here, even though the NSEC RR may not be returned. - // TODO: this part should be revised when we support NSEC3; ideally we - // should use more effective and efficient way to identify (whether and) - // in which way the zone is signed. - if (wild && (options & FIND_DNSSEC) != 0 && !need_nsec3 && + if (wild && dnssec_ctx.isNSEC() && found.second.find(RRType::NSEC()) != found.second.end()) { - flags = flags | RESULT_NSEC_SIGNED; + flags = (flags | RESULT_NSEC_SIGNED); } - if (!is_origin && ((options & FIND_GLUE_OK) == 0) && + if (!dnssec_ctx.isOrigin(name) && + ((dnssec_ctx.getOptions() & FIND_GLUE_OK) == 0) && nsi != found.second.end()) { // A NS RRset was found at the domain we were searching for. As it is // not at the origin of the zone, it is a delegation and indicates that @@ -821,66 +937,54 @@ DatabaseClient::Finder::findOnNameResult(const Name& name, // NSEC records in the name of the wildcard, not the substituted one, // so we need to search the tree again. ConstRRsetPtr nsec_rrset; // possibly used with DNSSEC, otherwise NULL - if ((options & FIND_DNSSEC) != 0 && !need_nsec3) { - if (wild) { - const FoundRRsets wfound = getRRsets(*wildname, NSEC_TYPES(), - true); - const FoundIterator nci = wfound.second.find(RRType::NSEC()); - if (nci != wfound.second.end()) { - nsec_rrset = nci->second; - } - } else { - const FoundIterator nci = found.second.find(RRType::NSEC()); - if (nci != found.second.end()) { - nsec_rrset = nci->second; - } - } + if (dnssec_ctx.isNSEC()) { + nsec_rrset = wild ? dnssec_ctx.getNSECRRset(Name(*wildname)) : + dnssec_ctx.getNSECRRset(found); } if (nsec_rrset) { // This log message covers both normal and wildcard cases, so we pass // NULL for 'wildname'. return (logAndCreateResult(name, NULL, type, NXRRSET, nsec_rrset, DATASRC_DATABASE_FOUND_NXRRSET_NSEC, - flags | RESULT_NSEC_SIGNED)); + (flags | RESULT_NSEC_SIGNED))); } return (logAndCreateResult(name, wildname, type, NXRRSET, nsec_rrset, wild ? DATASRC_DATABASE_WILDCARD_NXRRSET : - DATASRC_DATABASE_FOUND_NXRRSET, need_nsec3 ? - (flags | RESULT_NSEC3_SIGNED) : flags)); + DATASRC_DATABASE_FOUND_NXRRSET, + (flags | dnssec_ctx.getResultFlags()))); } ZoneFinder::ResultContext DatabaseClient::Finder::findNoNameResult(const Name& name, const RRType& type, - FindOptions options, const DelegationSearchResult& dresult, std::vector* - target, const bool need_nsec3) + target, FindDNSSECContext& dnssec_ctx) { - const bool dnssec_data = ((options & FIND_DNSSEC) != 0); - const bool need_nsec = (dnssec_data && !need_nsec3); // On entry to this method, we know that the database doesn't have any // entry for this name. Before returning NXDOMAIN, we need to check // for special cases. if (hasSubdomains(name.toText())) { - // Does the domain have a subdomain (i.e. it is an empty non-terminal)? + // Does the domain have a subdomain (i.e. it is an empty non-terminal) // If so, return NXRRSET instead of NXDOMAIN (as although the name does // not exist in the database, it does exist in the DNS tree). LOG_DEBUG(logger, DBG_TRACE_DETAILED, DATASRC_DATABASE_FOUND_EMPTY_NONTERMINAL). arg(accessor_->getDBName()).arg(name); - const ConstRRsetPtr nsec = need_nsec ? findNSECCover(name) : + const ConstRRsetPtr nsec = dnssec_ctx.isNSEC() ? findNSECCover(name) : ConstRRsetPtr(); - return (ResultContext(NXRRSET, nsec, nsec ? RESULT_NSEC_SIGNED : - (need_nsec3 ? RESULT_NSEC3_SIGNED : RESULT_DEFAULT))); - } else if ((options & NO_WILDCARD) == 0) { + if(dnssec_ctx.isNSEC() && (!nsec)){ + isc_throw(DataSourceError, + "no NSEC RR covers in the NSEC signed zone"); + } + return (ResultContext(NXRRSET, nsec, dnssec_ctx.getResultFlags())); + } else if ((dnssec_ctx.getOptions() & NO_WILDCARD) == 0) { // It's not an empty non-terminal and wildcard matching is not // disabled, so check for wildcards. If there is a wildcard match // (i.e. all results except NXDOMAIN) return it; otherwise fall // through to the NXDOMAIN case below. const ResultContext wcontext = - findWildcardMatch(name, type, options, dresult, target, - need_nsec3); + findWildcardMatch(name, type, dresult, target, dnssec_ctx); if (wcontext.code != NXDOMAIN) { return (wcontext); } @@ -890,11 +994,12 @@ DatabaseClient::Finder::findNoNameResult(const Name& name, const RRType& type, // NSEC records if requested). LOG_DEBUG(logger, DBG_TRACE_DETAILED, DATASRC_DATABASE_NO_MATCH). arg(accessor_->getDBName()).arg(name).arg(type).arg(getClass()); - const ConstRRsetPtr nsec = need_nsec ? findNSECCover(name) : + const ConstRRsetPtr nsec = dnssec_ctx.isNSEC() ? findNSECCover(name) : ConstRRsetPtr(); - return (ResultContext(NXDOMAIN, nsec, - nsec ? RESULT_NSEC_SIGNED : (need_nsec3 ? - RESULT_NSEC3_SIGNED : RESULT_DEFAULT))); + if(dnssec_ctx.isNSEC() && (!nsec)){ + isc_throw(DataSourceError, "no NSEC RR covers in the NSEC signed zone"); + } + return (ResultContext(NXDOMAIN, nsec, dnssec_ctx.getResultFlags())); } bool @@ -910,9 +1015,9 @@ DatabaseClient::Finder::isNSEC3() { bool DatabaseClient::Finder::isNSEC() { - // If an NSEC RRsets exists at the zone apex, it's quite likely that - // the zone is signed with NSEC. (If not the zone is more or less broken, - // but it's caller's responsibility how to handle such cases) + // If an NSEC RR exists at the zone apex, it's quite likely that + // the zone is signed with NSEC. (If not the zone is more or less broken, + // but it's caller's responsibility how to handle such cases). const FoundRRsets nsec_found = getRRsets(origin_.toText(), NSEC_TYPES(), false); const FoundIterator nfi(nsec_found.second.find(RRType::NSEC())); @@ -922,8 +1027,7 @@ DatabaseClient::Finder::isNSEC() { ZoneFinder::ResultContext DatabaseClient::Finder::findInternal(const Name& name, const RRType& type, std::vector* target, - const FindOptions options, - const bool is_nsec3) + const FindOptions options) { LOG_DEBUG(logger, DBG_TRACE_DETAILED, DATASRC_DATABASE_FIND_RECORDS) .arg(accessor_->getDBName()).arg(name).arg(type).arg(getClass()); @@ -961,22 +1065,16 @@ DatabaseClient::Finder::findInternal(const Name& name, const RRType& type, // - Requested name is a delegation point (NS only but not at the zone // apex - DNAME is ignored here as it redirects DNS names subordinate to // the owner name - the owner name itself is not redirected.) - const bool is_origin = (name == getOrigin()); - WantedTypes final_types(is_nsec3 ? FINAL_TYPES_NO_NSEC() : FINAL_TYPES()); - final_types.insert(type); - const FoundRRsets found = getRRsets(name.toText(), final_types, - !is_origin, NULL, - type == RRType::ANY()); + FindDNSSECContext dnssec_ctx(this, options, getOrigin()); + const FoundRRsets found = dnssec_ctx.getDNSSECRRset(name, type); if (found.first) { // Something found at the domain name. Look into it further to get // the final result. - return (findOnNameResult(name, type, options, is_origin, found, - NULL, target, is_nsec3)); + return (findOnNameResult(name, type, found, NULL, target, dnssec_ctx)); } else { // Did not find anything at all at the domain name, so check for // subdomains or wildcards. - return (findNoNameResult(name, type, options, dresult, target, - is_nsec3)); + return (findNoNameResult(name, type, dresult, target, dnssec_ctx)); } } diff --git a/src/lib/datasrc/database.h b/src/lib/datasrc/database.h index b9421ca8a4..2e8c88513d 100644 --- a/src/lib/datasrc/database.h +++ b/src/lib/datasrc/database.h @@ -673,6 +673,7 @@ public: DatabaseClient(isc::dns::RRClass rrclass, boost::shared_ptr accessor); + /// \brief Corresponding ZoneFinder implementation /// /// The zone finder implementation for database data sources. Similarly @@ -687,7 +688,126 @@ public: /// /// Methods directly corresponds to the ones in ZoneFinder. class Finder : public ZoneFinder { - public: + + /// \brief Helper to the findInterval. + /// + /// Get the ResultFlags for findInterval. If the zone is signed with + /// NSEC3, it will return RESULT_NSEC3_SIGNED. If it is signed with + /// NSEC, it wll return RESULT_NSEC_SIGNED. Other else it will return + /// RESULT_DEFAULT. It wraps getRRsets function to do some special + /// search, like searching NSEC RRset by getNSECRRset function, + /// searching DNSSEC related RRset and RRsig by getNSECRRset. + class FindDNSSECContext{ + public: + + /// \brief Constructor for FindDNSSECContext class. + /// + /// It initalize a helper for findInterval function. + /// + /// \param finderp The Finder piont for search. + /// \param options Search options. + /// \param origin The origin name for this finder. + FindDNSSECContext(Finder* finderp, const FindOptions options, + const isc::dns::Name& origin); + + /// \brief Get result flags of this query. + /// \return ResultFlags for this query. If the zone file is + /// signed with NSEC, is will return RESULT_NSEC_SIGNED with + /// dnssec query. If the zone file is signed with NSEC3, it + /// will return RESULT_NSEC3_SIGNED with dnssec query, others + /// it should return RESULT_DEFAULT. + ZoneFinder::FindResultFlags getResultFlags(); + + typedef std::pair > + FoundRRsets; + /// \brief Get DNSSEC RRset for the queried name. + /// + /// It should return the RRsets and RRsigs for the queried + /// name with designated type. + /// + /// \param name The queried name. + /// \param type The queried type. + /// \return RRsets and RRsigs that are matched. + FoundRRsets getDNSSECRRset(const isc::dns::Name& name, + const isc::dns::RRType& type); + + /// \brief Get the needed NSEC RRset. + /// + /// It should return the needed NSEC RRset. + /// + /// \param name The name which the NSEC RRset belong to. + /// \return the needed NSEC RRsets. + isc::dns::ConstRRsetPtr getNSECRRset(const isc::dns::Name& + name) const; + + /// \brief Get the needed NSEC RRset. + /// + /// It should return the needed NSEC RRset. + /// + /// \param found_set The RRset which contain the NSEC an other + /// type RRs. + /// \return the needed NSEC RRsets. + isc::dns::ConstRRsetPtr getNSECRRset(const FoundRRsets& + found_set) const; + + /// \brief Check whether the zone file is signed with NSECi3. + /// + /// It checks whether the zone file is signed with NSEC3. If + /// yes, return true, other else return false. + /// + /// \return True for NSEC3, false for other else. + bool isNSEC3(); + + /// \brief Check whether the zone file is signed with NSEC. + /// + /// It checks whether the zone file is signed with NSEC, If + /// yes, return true, other else return false. + /// + /// \return True for NSEC, false for other else. + bool isNSEC(); + + /// \brief Check whether the name is origin name of the zone. + /// + /// It checks whether the name is origin name of the zone. Yes + /// for the origin name, false for not. + /// + /// \param name The queried name. + /// \return True for origin name, false for not. + bool isOrigin(const isc::dns::Name& name) const; + + /// \brief get the options of queried. + /// + /// It return the queried options. + /// + /// \return It return the queried options. + ZoneFinder::FindOptions getOptions() const; + private: + + /// \brief Init the attributes in this entity. + /// + /// It should init the attributes of this entity. Check whether + /// it is the NSEC or NSEC3 zone file if it is a dnssec query. + /// + /// \note If the entity is initalized, no need to init it again. + void init(); + + /// \brief Check whether the entity is initalized. + /// + /// It should return true if the entity is inited, else return + /// false. + /// + /// \return True for inited, else return false. + bool isInited(); + DatabaseClient::Finder* finderp_; + ZoneFinder::ZoneFinder::FindOptions options_; + FindResultFlags flags_; + isc::dns::Name origin_; + bool is_nsec3_; + bool is_nsec_; + bool initialized_; + }; + + public: /// \brief Constructor /// /// \param database The database (shared with DatabaseClient) to @@ -706,19 +826,6 @@ public: virtual isc::dns::Name getOrigin() const; virtual isc::dns::RRClass getClass() const; - - /// \brief check whether zone is signed with nsec3 - /// - /// searches the NSEC3PARAM RRset in the zone apex, if it exists, the - /// zone looks signed with nsec3 - bool isNSEC3(); - - /// \brief check whether zone is signed with nsec - /// - /// searches the NSEC RRset in the zone apex, if it exists, the - /// zone looks signed with nsec - bool isNSEC(); - /// \brief Find an RRset in the datasource /// /// Searches the datasource for an RRset of the given name and @@ -791,10 +898,22 @@ public: return (*accessor_); } + /// \brief check whether zone is signed with nsec + /// + /// searches the NSEC3PARAM RRset in the zone apex, if it exists, the + /// zone looks signed with nsec + bool isNSEC(); + /// \brief check whether zone is signed with nsec3 + /// + /// searches the NSEC3PARAM RRset in the zone apex, if it exists, the + /// zone looks signed with nsec3 + bool isNSEC3(); + private: boost::shared_ptr accessor_; const int zone_id_; const isc::dns::Name origin_; + /// \brief Shortcut name for the result of getRRsets typedef std::pair > FoundRRsets; @@ -814,9 +933,8 @@ public: const isc::dns::RRType& type, std::vector* target, - const FindOptions options = FIND_DEFAULT, - const bool need_nsec3 = false); - + const FindOptions options = FIND_DEFAULT); + public: /// \brief Searches database for RRsets of one domain. /// /// This method scans RRs of single domain specified by name and @@ -851,6 +969,7 @@ public: const std::string* construct_name = NULL, bool any = false); + private: /// \brief Search result of \c findDelegationPoint(). /// /// This is a tuple combining the result of the search - a status code @@ -946,15 +1065,13 @@ public: /// /// \param name The name to find /// \param type The RRType to find - /// \param options Options about how to search. See the documentation - /// for ZoneFinder::FindOptions. /// \param dresult Result of the search through the zone for a /// delegation. /// \param target If the type happens to be ANY, it will insert all /// the RRsets of the found name (if any is found) here instead /// of being returned by the result. - /// \param need_nsec3 When zone is signed with nsec3, no need to find - /// nsec rrset + /// \param dnssec_ctx The dnssec context, it is a DNSSEC wrapper for + /// find function. /// \return Tuple holding the result of the search - the RRset of the /// wildcard records matching the name, together with a status /// indicating the match type (e.g. CNAME at the wildcard @@ -962,13 +1079,11 @@ public: /// success due to an exact match). Also returned if there /// is no match is an indication as to whether there was an /// NXDOMAIN or an NXRRSET. - ResultContext findWildcardMatch( - const isc::dns::Name& name, - const isc::dns::RRType& type, - const FindOptions options, - const DelegationSearchResult& dresult, - std::vector* target, - const bool need_nsec3); + ResultContext findWildcardMatch(const isc::dns::Name& name, + const isc::dns::RRType& type, + const DelegationSearchResult& dresult, + std::vector* + target, FindDNSSECContext& dnssec_ctx); /// \brief Handle matching results for name /// @@ -989,9 +1104,6 @@ public: /// /// \param name The name to find /// \param type The RRType to find - /// \param options Options about how to search. See the documentation - /// for ZoneFinder::FindOptions. - /// \param is_origin If name is the zone's origin name. /// \param found A set of found RRsets in the search for the name /// and type. It could contain one or more of the requested /// type, CNAME, NS, and NSEC RRsets of the name. @@ -1001,8 +1113,9 @@ public: /// it's NULL in the case of non wildcard match. /// \param target When the query is any, this must be set to a vector /// where the result will be stored. - /// \param need_nsec3 When zone is signed with nsec3, no need to find - /// nsec rrset + /// \param dnssec_ctx The dnssec context, it is a DNSSEC wrapper for + /// find function. + /// \return Tuple holding the result of the search - the RRset of the /// wildcard records matching the name, together with a status /// indicating the match type (corresponding to the each of @@ -1011,12 +1124,10 @@ public: /// method. ResultContext findOnNameResult(const isc::dns::Name& name, const isc::dns::RRType& type, - const FindOptions options, - const bool is_origin, const FoundRRsets& found, const std::string* wildname, std::vector* - target, const bool need_nsec3); + target, FindDNSSECContext& dnssec_ctx); /// \brief Handle no match for name /// @@ -1041,8 +1152,8 @@ public: /// \param target If the query is for type ANY, the successfull result, /// if there happens to be one, will be returned through the /// parameter, as it doesn't fit into the result. - /// \param need_nsec3 When zone is signed with nsec3, no need to find - /// nsec rrset + /// \param dnssec_ctx The dnssec context, it is a DNSSEC wrapper for + /// find function. /// \return Tuple holding the result of the search - the RRset of the /// wildcard records matching the name, together with a status /// indicating the match type (e.g. CNAME at the wildcard @@ -1050,10 +1161,9 @@ public: /// success due to an exact match). ResultContext findNoNameResult(const isc::dns::Name& name, const isc::dns::RRType& type, - FindOptions options, const DelegationSearchResult& dresult, std::vector* - targeti, const bool need_nsec3); + target, FindDNSSECContext& dnssec_ctx); /// Logs condition and creates result /// @@ -1106,6 +1216,8 @@ public: /// To find stuff in the result of getRRsets. typedef std::map::const_iterator FoundIterator; + + }; /// \brief Find a zone in the database diff --git a/src/lib/datasrc/tests/database_unittest.cc b/src/lib/datasrc/tests/database_unittest.cc index 3c1e892dfd..bd99f5de67 100644 --- a/src/lib/datasrc/tests/database_unittest.cc +++ b/src/lib/datasrc/tests/database_unittest.cc @@ -2292,11 +2292,18 @@ TYPED_TEST(DatabaseClientTest, wildcardNXRRSET_NSEC) { Name("*.wild.example.org"), ZoneFinder::FIND_DNSSEC); } -TYPED_TEST(DatabaseClientTest, dbNegativeCaseFind) { - // ZoneFinder::find() for negative cases should show whether the zone is - // signed with NSEC or NSEC3, that is good for upper layer caller. +TYPED_TEST(DatabaseClientTest, nsec3FlagFindDB) { + // ZoneFinder::find() for negative cases and wildcard cases should check + // whether the zone is signed with NSEC or NSEC3. If it is signed with + // NSEC3, RESULT_NSEC3_SIGNED flag should be returned. That is good for + // upper layer caller. - // First off, everything should be okay if no NSEC3PARAM rrset + // First off, everything should be okay if no NSEC3PARAM rrset. If + // NSEC3PARAM RRset doesn't exist and NSEC RRset exist at apex, it looks + // like signed with NSEC, and the RESULT_NSEC_SIGNED flag should be return. + + // Check NXDOMAIN case in NSEC signed zone, and RESULT_NSEC_SIGNED flag + // should be returned to upper layer caller. this->expected_rdatas_.clear(); this->expected_sig_rdatas_.clear(); this->expected_rdatas_.push_back("www2.example.org. A AAAA NSEC RRSIG"); @@ -2309,6 +2316,9 @@ TYPED_TEST(DatabaseClientTest, dbNegativeCaseFind) { ZoneFinder::NXDOMAIN, this->expected_rdatas_, this->expected_sig_rdatas_, ZoneFinder::RESULT_NSEC_SIGNED, Name("www.example.org."), ZoneFinder::FIND_DNSSEC); + + // Check NXRRSET case in NSEC signed zone, and RESULT_NSEC_SIGNED flag + // should be return. this->expected_rdatas_.clear(); this->expected_sig_rdatas_.clear(); this->expected_rdatas_.push_back("www2.example.org. A AAAA NSEC RRSIG"); @@ -2316,11 +2326,12 @@ TYPED_TEST(DatabaseClientTest, dbNegativeCaseFind) { "20000201000000 12345 example.org. " "FAKEFAKEFAKE"); doFindTest(*finder, isc::dns::Name("www.example.org."), - isc::dns::RRType::TXT(), isc::dns::RRType::NSEC(), - this->rrttl_, ZoneFinder::NXRRSET, - this->expected_rdatas_, this->expected_sig_rdatas_, - ZoneFinder::RESULT_NSEC_SIGNED, isc::dns::Name::ROOT_NAME(), - ZoneFinder::FIND_DNSSEC); + isc::dns::RRType::TXT(), isc::dns::RRType::NSEC(), this->rrttl_, + ZoneFinder::NXRRSET, this->expected_rdatas_, + this->expected_sig_rdatas_, ZoneFinder::RESULT_NSEC_SIGNED, + isc::dns::Name::ROOT_NAME(), ZoneFinder::FIND_DNSSEC); + + // Check wildcase cases, and the RESULT_NSEC_SIGNED should be return. this->expected_rdatas_.clear(); this->expected_sig_rdatas_.clear(); this->expected_rdatas_.push_back("192.0.2.5"); @@ -2346,26 +2357,10 @@ TYPED_TEST(DatabaseClientTest, dbNegativeCaseFind) { this->expected_sig_rdatas_, (ZoneFinder::RESULT_WILDCARD | ZoneFinder::RESULT_NSEC_SIGNED), Name("*.wild.example.org"), ZoneFinder::FIND_DNSSEC); - this->updater_ = this->client_->getUpdater(this->zname_, false); - this->rrset_.reset(new RRset(this->zname_, this->qclass_, - isc::dns::RRType::NSEC3PARAM(), this->rrttl_)); - this->rrset_->addRdata(rdata::createRdata(isc::dns::RRType::NSEC3PARAM(), - this->rrset_->getClass(), "1 0 12 aabbccdd")); - this->updater_->addRRset(*this->rrset_); - this->updater_->commit(); - try { - this->expected_rdatas_.clear(); - this->expected_sig_rdatas_.clear(); - doFindTest(this->updater_->getFinder(), Name("www1.example.org."), - this->qtype_, this->qtype_, this->rrttl_, - ZoneFinder::NXDOMAIN, this->expected_rdatas_, - this->expected_sig_rdatas_, ZoneFinder::RESULT_NSEC3_SIGNED, - Name::ROOT_NAME(), ZoneFinder::FIND_DNSSEC); - } catch (const DataSourceError&) {} - // The following test should be tested in zone which is signed by NSEC3 -#if 0 - // Then, if NSEC3PARAM exists at the origin, the flags of result should + + // Then, if NSEC3PARAM exists at the apex, the flags of result should // contain RESULT_NSEC3_SIGNED flag when NXDOMAIN NXRRSET or wildcard + // cases. // Add NSEC3PARAM RRSET at the apex of the zone. It looks weird if the // zone only has NSEC3PARM RRset (but no NSEC3s), but it is okay for unit @@ -2377,23 +2372,27 @@ TYPED_TEST(DatabaseClientTest, dbNegativeCaseFind) { this->rrset_->getClass(), "1 0 12 aabbccdd")); this->updater_->addRRset(*this->rrset_); - // check NXDOMAIN + + // check NXDOMAIN, it should set RESULT_NSEC3_SIGNED in the flags. this->expected_rdatas_.clear(); this->expected_sig_rdatas_.clear(); - doFindTest(this->updater_->getFinder(), - isc::dns::Name("www1.example.org."), this->qtype_, this->qtype_, - this->rrttl_, ZoneFinder::NXDOMAIN, this->expected_rdatas_, - this->expected_sig_rdatas_, ZoneFinder::RESULT_NSEC3_SIGNED, - isc::dns::Name::ROOT_NAME(), ZoneFinder::FIND_DNSSEC); - // check NXRRSET + doFindTest(this->updater_->getFinder(), Name("www1.example.org."), + this->qtype_, this->qtype_, this->rrttl_, ZoneFinder::NXDOMAIN, + this->expected_rdatas_, this->expected_sig_rdatas_, + ZoneFinder::RESULT_NSEC3_SIGNED,Name::ROOT_NAME(), + ZoneFinder::FIND_DNSSEC); + + // check NXRRSET, it should set RESULT_NSEC3_SIGNED in the flags. this->expected_rdatas_.clear(); this->expected_sig_rdatas_.clear(); doFindTest(this->updater_->getFinder(), Name("www.example.org."), RRType::TXT(), RRType::TXT(), this->rrttl_, ZoneFinder::NXRRSET, this->expected_rdatas_, this->expected_sig_rdatas_, ZoneFinder::RESULT_NSEC3_SIGNED, - isc::dns::Name::ROOT_NAME(), ZoneFinder::FIND_DNSSEC); - // check flags if wildcard matches + Name::ROOT_NAME(), ZoneFinder::FIND_DNSSEC); + + // check flags if wildcard matches, it should set RESULT_NSEC3_SIGNED in + // the flags. this->expected_rdatas_.push_back("192.0.2.5"); this->expected_sig_rdatas_.push_back("A 5 3 3600 20000101000000 " "20000201000000 12345 example.org. " @@ -2403,16 +2402,17 @@ TYPED_TEST(DatabaseClientTest, dbNegativeCaseFind) { this->expected_rdatas_, this->expected_sig_rdatas_, ZoneFinder::RESULT_WILDCARD | ZoneFinder::RESULT_NSEC3_SIGNED, Name::ROOT_NAME(), ZoneFinder::FIND_DNSSEC); - // check flags if NXRRSET in wildcard case + + // check flags if NXRRSET in wildcard case, it should set + // RESULT_NSEC3_SIGNED in the flags. this->expected_rdatas_.clear(); this->expected_sig_rdatas_.clear(); doFindTest(this->updater_->getFinder(), Name("b.a.wild.example.org"), RRType::TXT(), RRType::TXT(), this->rrttl_, ZoneFinder::NXRRSET, this->expected_rdatas_, this->empty_rdatas_, (ZoneFinder::RESULT_WILDCARD | - ZoneFinder::RESULT_NSEC3_SIGNED), - Name::ROOT_NAME(), ZoneFinder::FIND_DNSSEC); -#endif + ZoneFinder::RESULT_NSEC3_SIGNED), Name::ROOT_NAME(), + ZoneFinder::FIND_DNSSEC); } TYPED_TEST(DatabaseClientTest, NXDOMAIN_NSEC) { @@ -2444,14 +2444,17 @@ TYPED_TEST(DatabaseClientTest, NXDOMAIN_NSEC) { if (!this->is_mock_) { return; // We don't make the real DB to throw } - EXPECT_NO_THROW(doFindTest(*finder, + // If the zone is signed with NSEC, find function should throw an error + // when no NSEC RRset for NXDOMAIN case. + EXPECT_THROW(doFindTest(*finder, isc::dns::Name("notimplnsec.example.org."), isc::dns::RRType::TXT(), isc::dns::RRType::NSEC(), this->rrttl_, ZoneFinder::NXDOMAIN, this->empty_rdatas_, this->empty_rdatas_, ZoneFinder::RESULT_DEFAULT, - Name::ROOT_NAME(), ZoneFinder::FIND_DNSSEC)); + Name::ROOT_NAME(), ZoneFinder::FIND_DNSSEC), + DataSourceError); } TYPED_TEST(DatabaseClientTest, emptyNonterminalNSEC) { @@ -2471,14 +2474,17 @@ TYPED_TEST(DatabaseClientTest, emptyNonterminalNSEC) { if (!this->is_mock_) { return; // We don't make the real DB to throw } - EXPECT_NO_THROW(doFindTest(*finder, + // If the zone is signed with NSEC, find function should throw an error + // when no NSEC RRset for NXRRset case + EXPECT_THROW(doFindTest(*finder, isc::dns::Name("here.wild.example.org."), isc::dns::RRType::TXT(), isc::dns::RRType::NSEC(), this->rrttl_, ZoneFinder::NXRRSET, this->empty_rdatas_, this->empty_rdatas_, ZoneFinder::RESULT_DEFAULT, - Name::ROOT_NAME(), ZoneFinder::FIND_DNSSEC)); + Name::ROOT_NAME(), ZoneFinder::FIND_DNSSEC), + DataSourceError); } TYPED_TEST(DatabaseClientTest, anyFromFind) {