• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

PowerDNS / pdns / 12595591960

03 Jan 2025 09:27AM UTC coverage: 62.774% (+2.5%) from 60.245%
12595591960

Pull #15008

github

web-flow
Merge c2a2749d3 into 788f396a7
Pull Request #15008: Do not follow CNAME records for ANY or CNAME queries

30393 of 78644 branches covered (38.65%)

Branch coverage included in aggregate %.

105822 of 138350 relevant lines covered (76.49%)

4613078.44 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

81.48
/pdns/recursordist/aggressive_nsec.hh
1
/*
2
 * This file is part of PowerDNS or dnsdist.
3
 * Copyright -- PowerDNS.COM B.V. and its contributors
4
 *
5
 * This program is free software; you can redistribute it and/or modify
6
 * it under the terms of version 2 of the GNU General Public License as
7
 * published by the Free Software Foundation.
8
 *
9
 * In addition, for the avoidance of any doubt, permission is granted to
10
 * link this program with OpenSSL and to (re)distribute the binaries
11
 * produced as the result of such linking.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU General Public License
19
 * along with this program; if not, write to the Free Software
20
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21
 */
22
#pragma once
23

24
#include <atomic>
25
#include <boost/utility.hpp>
26
#include <boost/multi_index_container.hpp>
27
#include <boost/multi_index/ordered_index.hpp>
28
#include <boost/multi_index/hashed_index.hpp>
29
#include <boost/multi_index/key_extractors.hpp>
30
#include <boost/multi_index/sequenced_index.hpp>
31

32
using namespace ::boost::multi_index;
33

34
#include "base32.hh"
35
#include "dnsname.hh"
36
#include "dnsrecords.hh"
37
#include "lock.hh"
38
#include "stat_t.hh"
39
#include "logger.hh"
40
#include "validate.hh"
41

42
class AggressiveNSECCache
43
{
44
public:
45
  static constexpr uint8_t s_default_maxNSEC3CommonPrefix = 10;
46
  static uint64_t s_nsec3DenialProofMaxCost;
47
  static uint8_t s_maxNSEC3CommonPrefix;
48

49
  AggressiveNSECCache(uint64_t entries) :
50
    d_maxEntries(entries)
51
  {
206✔
52
  }
206✔
53

54
  void setMaxEntries(uint64_t number)
55
  {
×
56
    d_maxEntries = number;
×
57
  }
×
58

59
  static bool nsec3Disabled()
60
  {
41,539✔
61
    return s_maxNSEC3CommonPrefix == 0;
41,539✔
62
  }
41,539✔
63

64
  void insertNSEC(const DNSName& zone, const DNSName& owner, const DNSRecord& record, const std::vector<std::shared_ptr<const RRSIGRecordContent>>& signatures, bool nsec3, const DNSName& qname = g_rootdnsname, QType qtype = QType::ENT);
65
  bool getDenial(time_t, const DNSName& name, const QType& type, std::vector<DNSRecord>& ret, int& res, const ComboAddress& who, const boost::optional<std::string>& routingTag, bool doDNSSEC, pdns::validation::ValidationContext& validationContext, const OptLog& log = std::nullopt);
66

67
  void removeZoneInfo(const DNSName& zone, bool subzones);
68

69
  uint64_t getEntriesCount() const
70
  {
189✔
71
    return d_entriesCount;
189✔
72
  }
189✔
73

74
  uint64_t getNSECHits() const
75
  {
123✔
76
    return d_nsecHits;
123✔
77
  }
123✔
78

79
  uint64_t getNSEC3Hits() const
80
  {
123✔
81
    return d_nsec3Hits;
123✔
82
  }
123✔
83

84
  uint64_t getNSECWildcardHits() const
85
  {
123✔
86
    return d_nsecWildcardHits;
123✔
87
  }
123✔
88

89
  uint64_t getNSEC3WildcardHits() const
90
  {
123✔
91
    return d_nsec3WildcardHits;
123✔
92
  }
123✔
93

94
  // exported for unit test purposes
95
  static bool isSmallCoveringNSEC3(const DNSName& owner, const std::string& nextHash);
96

97
  void prune(time_t now);
98
  size_t dumpToFile(pdns::UniqueFilePtr& filePtr, const struct timeval& now);
99

100
private:
101
  struct ZoneEntry
102
  {
103
    ZoneEntry(const DNSName& zone) :
104
      d_zone(zone)
105
    {
217✔
106
    }
217✔
107

108
    ZoneEntry(const DNSName& zone, const std::string& salt, uint16_t iterations, bool nsec3) :
109
      d_zone(zone), d_salt(salt), d_iterations(iterations), d_nsec3(nsec3)
110
    {
×
111
    }
×
112

113
    struct HashedTag
114
    {
115
    };
116
    struct SequencedTag
117
    {
118
    };
119
    struct OrderedTag
120
    {
121
    };
122

123
    struct CacheEntry
124
    {
125
      std::shared_ptr<const DNSRecordContent> d_record;
126
      std::vector<std::shared_ptr<const RRSIGRecordContent>> d_signatures;
127

128
      DNSName d_owner;
129
      DNSName d_next;
130
      DNSName d_qname; // of the query data that lead to this entry being created/updated
131
      time_t d_ttd;
132
      QType d_qtype; // of the query data that lead to this entry being created/updated
133
    };
134

135
    typedef multi_index_container<
136
      CacheEntry,
137
      indexed_by<
138
        ordered_unique<tag<OrderedTag>,
139
                       member<CacheEntry, const DNSName, &CacheEntry::d_owner>,
140
                       CanonDNSNameCompare>,
141
        sequenced<tag<SequencedTag>>,
142
        hashed_non_unique<tag<HashedTag>,
143
                          member<CacheEntry, const DNSName, &CacheEntry::d_owner>>>>
144
      cache_t;
145

146
    cache_t d_entries;
147
    const DNSName d_zone;
148
    std::string d_salt;
149
    uint16_t d_iterations{0};
150
    bool d_nsec3{false};
151
  };
152

153
  std::shared_ptr<LockGuarded<ZoneEntry>> getZone(const DNSName& zone);
154
  std::shared_ptr<LockGuarded<ZoneEntry>> getBestZone(const DNSName& zone);
155
  bool getNSECBefore(time_t now, std::shared_ptr<LockGuarded<ZoneEntry>>& zoneEntry, const DNSName& name, ZoneEntry::CacheEntry& entry);
156
  bool getNSEC3(time_t now, std::shared_ptr<LockGuarded<ZoneEntry>>& zoneEntry, const DNSName& name, ZoneEntry::CacheEntry& entry);
157
  bool getNSEC3Denial(time_t now, std::shared_ptr<LockGuarded<ZoneEntry>>& zoneEntry, std::vector<DNSRecord>& soaSet, std::vector<std::shared_ptr<const RRSIGRecordContent>>& soaSignatures, const DNSName& name, const QType& type, std::vector<DNSRecord>& ret, int& res, bool doDNSSEC, const OptLog&, pdns::validation::ValidationContext& validationContext);
158
  bool synthesizeFromNSEC3Wildcard(time_t now, const DNSName& name, const QType& type, std::vector<DNSRecord>& ret, int& res, bool doDNSSEC, ZoneEntry::CacheEntry& nextCloser, const DNSName& wildcardName, const OptLog&);
159
  bool synthesizeFromNSECWildcard(time_t now, const DNSName& name, const QType& type, std::vector<DNSRecord>& ret, int& res, bool doDNSSEC, ZoneEntry::CacheEntry& nsec, const DNSName& wildcardName, const OptLog&);
160

161
  /* slowly updates d_entriesCount */
162
  void updateEntriesCount(SuffixMatchTree<std::shared_ptr<LockGuarded<ZoneEntry>>>& zones);
163

164
  SharedLockGuarded<SuffixMatchTree<std::shared_ptr<LockGuarded<ZoneEntry>>>> d_zones;
165
  pdns::stat_t d_nsecHits{0};
166
  pdns::stat_t d_nsec3Hits{0};
167
  pdns::stat_t d_nsecWildcardHits{0};
168
  pdns::stat_t d_nsec3WildcardHits{0};
169
  pdns::stat_t d_entriesCount{0};
170
  std::atomic<uint64_t> d_maxEntries{0};
171
};
172

173
extern std::unique_ptr<AggressiveNSECCache> g_aggressiveNSECCache;
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc