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

PowerDNS / pdns / 9418798096

07 Jun 2024 02:38PM UTC coverage: 64.612% (+0.002%) from 64.61%
9418798096

Pull #14057

github

web-flow
Merge 3ef28144e into b1d2ec1c5
Pull Request #14057: Auth: fix a crash and some cleanup in the auth-catalogzone.cc

37074 of 88162 branches covered (42.05%)

Branch coverage included in aggregate %.

23 of 50 new or added lines in 4 files covered. (46.0%)

45 existing lines in 14 files now uncovered.

124373 of 161708 relevant lines covered (76.91%)

5379791.12 hits per line

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

90.0
/modules/lmdbbackend/lmdbbackend.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

23
#pragma once
24
#include "pdns/dnsbackend.hh"
25
#include "ext/lmdb-safe/lmdb-typed.hh"
26

27
template <class T, typename std::enable_if<std::is_same<T, DNSName>::value, T>::type* = nullptr>
28
std::string keyConv(const T& t)
29
{
711,935✔
30
  /* www.ds9a.nl -> nl0ds9a0www0
31
     root -> 0   <- we need this to keep lmdb happy
32
     nl -> nl0
33
     
34
  */
35
  if (t.empty()) {
711,935!
36
    throw std::out_of_range(std::string(__PRETTY_FUNCTION__) + " Attempt to serialize an unset dnsname");
×
37
  }
×
38

39
  if (t.isRoot()) {
711,935✔
40
    return std::string(1, (char)0);
5,741✔
41
  }
5,741✔
42

43
  std::string in = t.labelReverse().toDNSStringLC(); // www.ds9a.nl is now 2nl4ds9a3www0
706,194✔
44
  std::string ret;
706,194✔
45
  ret.reserve(in.size());
706,194✔
46

47
  for (auto iter = in.begin(); iter != in.end(); ++iter) {
1,434,847!
48
    uint8_t len = *iter;
1,434,847✔
49
    if (iter != in.begin())
1,434,847✔
50
      ret.append(1, (char)0);
728,653✔
51
    if (!len)
1,434,847✔
52
      break;
706,194✔
53

54
    ret.append(&*(iter + 1), len);
728,653✔
55
    iter += len;
728,653✔
56
  }
728,653✔
57
  return ret;
706,194✔
58
}
711,935✔
59

60
class LMDBBackend : public DNSBackend
61
{
62
public:
63
  explicit LMDBBackend(const string& suffix = "");
64

65
  bool list(const DNSName& target, int id, bool include_disabled) override;
66

67
  bool getDomainInfo(const DNSName& domain, DomainInfo& di, bool getserial = true) override;
68
  bool createDomain(const DNSName& domain, const DomainInfo::DomainKind kind, const vector<ComboAddress>& primaries, const string& account) override;
69

70
  bool startTransaction(const DNSName& domain, int domain_id = -1) override;
71
  bool commitTransaction() override;
72
  bool abortTransaction() override;
73
  bool feedRecord(const DNSResourceRecord& r, const DNSName& ordername, bool ordernameIsNSEC3 = false) override;
74
  bool feedEnts(int domain_id, map<DNSName, bool>& nonterm) override;
75
  bool feedEnts3(int domain_id, const DNSName& domain, map<DNSName, bool>& nonterm, const NSEC3PARAMRecordContent& ns3prc, bool narrow) override;
76
  bool replaceRRSet(uint32_t domain_id, const DNSName& qname, const QType& qt, const vector<DNSResourceRecord>& rrset) override;
77
  bool replaceComments(uint32_t domain_id, const DNSName& qname, const QType& qt, const vector<Comment>& comments) override;
78

79
  void getAllDomains(vector<DomainInfo>* domains, bool doSerial, bool include_disabled) override;
80
  void lookup(const QType& type, const DNSName& qdomain, int zoneId, DNSPacket* p = nullptr) override;
81
  bool get(DNSResourceRecord& rr) override;
82
  bool get(DNSZoneRecord& dzr) override;
83

84
  // secondary support
85
  void getUnfreshSecondaryInfos(vector<DomainInfo>* domains) override;
86
  void setStale(uint32_t domain_id) override;
87
  void setFresh(uint32_t domain_id) override;
88

89
  // primary support
90
  void getUpdatedPrimaries(vector<DomainInfo>& updatedDomains, std::unordered_set<DNSName>& catalogs, CatalogHashMap& catalogHashes) override;
91
  void setNotified(uint32_t id, uint32_t serial) override;
92

93
  // catalog zones
94
  bool getCatalogMembers(const DNSName& catalog, vector<CatalogInfo>& members, CatalogInfo::CatalogType type) override;
95
  bool setOptions(const DNSName& domain, const std::string& options) override;
96
  bool setCatalog(const DNSName& domain, const DNSName& options) override;
97

98
  bool setPrimaries(const DNSName& domain, const vector<ComboAddress>& primaries) override;
99
  bool setKind(const DNSName& domain, const DomainInfo::DomainKind kind) override;
100
  bool getAllDomainMetadata(const DNSName& name, std::map<std::string, std::vector<std::string>>& meta) override;
101
  bool getDomainMetadata(const DNSName& name, const std::string& kind, std::vector<std::string>& meta) override
102
  {
2,602✔
103
    //    std::cout<<"Request for metadata items for zone "<<name<<", kind "<<kind<<endl;
104
    meta.clear();
2,602✔
105
    std::map<std::string, std::vector<std::string>> metas;
2,602✔
106
    if (getAllDomainMetadata(name, metas)) {
2,602!
107
      for (const auto& m : metas) {
2,871✔
108
        if (m.first == kind) {
2,640✔
109
          meta = m.second;
491✔
110
          return true;
491✔
111
        }
491✔
112
      }
2,640✔
113
      return true;
2,111✔
114
    }
2,602✔
UNCOV
115
    return false;
×
116
  }
2,602✔
117

118
  bool setDomainMetadata(const DNSName& name, const std::string& kind, const std::vector<std::string>& meta) override;
119
  bool setAccount(const DNSName& domain, const std::string& account) override;
120
  bool deleteDomain(const DNSName& domain) override;
121

122
  bool getDomainKeys(const DNSName& name, std::vector<KeyData>& keys) override;
123
  bool removeDomainKey(const DNSName& name, unsigned int id) override;
124
  bool addDomainKey(const DNSName& name, const KeyData& key, int64_t& id) override;
125
  bool activateDomainKey(const DNSName& name, unsigned int id) override;
126
  bool deactivateDomainKey(const DNSName& name, unsigned int id) override;
127
  bool publishDomainKey(const DNSName& name, unsigned int id) override;
128
  bool unpublishDomainKey(const DNSName& name, unsigned int id) override;
129

130
  // TSIG
131
  bool getTSIGKey(const DNSName& name, DNSName& algorithm, string& content) override;
132
  bool setTSIGKey(const DNSName& name, const DNSName& algorithm, const string& content) override;
133
  bool deleteTSIGKey(const DNSName& name) override;
134
  bool getTSIGKeys(std::vector<struct TSIGKey>& keys) override;
135

136
  // DNSSEC
137

138
  bool getBeforeAndAfterNamesAbsolute(uint32_t id, const DNSName& qname, DNSName& unhashed, DNSName& before, DNSName& after) override;
139

140
  bool getBeforeAndAfterNames(uint32_t id, const DNSName& zonename, const DNSName& qname, DNSName& before, DNSName& after) override;
141

142
  bool updateDNSSECOrderNameAndAuth(uint32_t domain_id, const DNSName& qname, const DNSName& ordername, bool auth, const uint16_t qtype = QType::ANY) override;
143

144
  bool updateEmptyNonTerminals(uint32_t domain_id, set<DNSName>& insert, set<DNSName>& erase, bool remove) override;
145

146
  bool doesDNSSEC() override
147
  {
988✔
148
    return true;
988✔
149
  }
988✔
150

151
  // other
152
  string directBackendCmd(const string& query) override;
153

154
  // functions to use without constructing a backend object
155
  static std::pair<uint32_t, uint32_t> getSchemaVersionAndShards(std::string& filename);
156
  static bool upgradeToSchemav5(std::string& filename);
157

158
private:
159
  struct compoundOrdername
160
  {
161
    std::string operator()(uint32_t id, const DNSName& t, uint16_t qtype)
162
    {
636,101✔
163
      std::string ret = operator()(id, t);
636,101✔
164
      uint16_t qt = htons(qtype);
636,101✔
165
      ret.append((char*)&qt, 2);
636,101✔
166
      return ret;
636,101✔
167
    }
636,101✔
168
    std::string operator()(uint32_t id, const DNSName& t)
169
    {
701,721✔
170
      std::string ret = operator()(id);
701,721✔
171
      ret += keyConv(t);
701,721✔
172
      ret.append(1, (char)0); // this means '00' really ends the zone
701,721✔
173
      return ret;
701,721✔
174
    }
701,721✔
175
    std::string operator()(uint32_t id)
176
    {
703,098✔
177
      std::string ret;
703,098✔
178
      id = htonl(id);
703,098✔
179
      ret.assign((char*)&id, 4);
703,098✔
180
      return ret;
703,098✔
181
    }
703,098✔
182

183
    std::string operator()(const DNSResourceRecord& rr)
184
    {
×
185
      return operator()(rr.domain_id, rr.qname, rr.qtype.getCode());
×
186
    }
×
187

188
    static uint32_t getDomainID(const string_view& key)
189
    {
272,203✔
190
      uint32_t ret;
272,203✔
191
      memcpy(&ret, &key[0], sizeof(ret));
272,203✔
192
      return ntohl(ret);
272,203✔
193
    }
272,203✔
194

195
    static DNSName getQName(const string_view& key)
196
    {
271,831✔
197
      /* www.ds9a.nl -> nl0ds9a0www0
198
         root -> 0   <- we need this to keep lmdb happy
199
         nl -> nl0 */
200
      DNSName ret;
271,831✔
201
      auto iter = key.cbegin() + 4;
271,831✔
202
      auto end = key.cend() - 2;
271,831✔
203
      while (iter < end) {
544,102!
204
        auto startpos = iter;
544,102✔
205
        while (iter != end && *iter)
3,336,853!
206
          ++iter;
2,792,751✔
207
        if (iter == startpos)
544,102✔
208
          break;
271,831✔
209
        string part(&*startpos, iter - startpos);
272,271✔
210
        ret.prependRawLabel(part);
272,271✔
211
        //        cout << "Prepending part: "<<part<<endl;
212
        if (iter != end)
272,271!
213
          ++iter;
272,271✔
214
      }
272,271✔
215
      if (ret.empty())
271,831✔
216
        return g_rootdnsname;
5,430✔
217
      return ret;
266,401✔
218
    }
271,831✔
219

220
    static QType getQType(const string_view& key)
221
    {
751,647✔
222
      uint16_t ret;
751,647✔
223
      memcpy(&ret, &key[key.size() - 2], sizeof(ret));
751,647✔
224
      return QType(ntohs(ret));
751,647✔
225
    }
751,647✔
226
  };
227

228
public:
229
  struct DomainMeta
230
  {
231
    DNSName domain;
232
    string key;
233
    string value;
234
  };
235
  struct KeyDataDB
236
  {
237
    DNSName domain;
238
    std::string content;
239
    unsigned int flags{0};
240
    bool active{true};
241
    bool published{true};
242
  };
243
  class LMDBResourceRecord : public DNSResourceRecord
244
  {
245
  public:
246
    LMDBResourceRecord() = default;
385,964✔
247
    LMDBResourceRecord(const DNSResourceRecord& rr) :
248
      DNSResourceRecord(rr), ordername(false) {}
325,638✔
249

250
    bool ordername{false};
251
  };
252

253
private:
254
  typedef TypedDBI<DomainInfo,
255
                   index_on<DomainInfo, DNSName, &DomainInfo::zone>>
256
    tdomains_t;
257

258
  typedef TypedDBI<DomainMeta,
259
                   index_on<DomainMeta, DNSName, &DomainMeta::domain>>
260
    tmeta_t;
261

262
  typedef TypedDBI<KeyDataDB,
263
                   index_on<KeyDataDB, DNSName, &KeyDataDB::domain>>
264
    tkdb_t;
265

266
  typedef TypedDBI<TSIGKey,
267
                   index_on<TSIGKey, DNSName, &TSIGKey::name>>
268
    ttsig_t;
269

270
  int d_asyncFlag;
271

272
  struct RecordsDB
273
  {
274
    shared_ptr<MDBEnv> env;
275
    MDBDbi dbi;
276
  };
277

278
  struct RecordsROTransaction
279
  {
280
    RecordsROTransaction(MDBROTransaction&& intxn) :
281
      txn(std::move(intxn))
282
    {}
10,946✔
283
    shared_ptr<RecordsDB> db;
284
    MDBROTransaction txn;
285
  };
286
  struct RecordsRWTransaction
287
  {
288
    RecordsRWTransaction(MDBRWTransaction&& intxn) :
289
      txn(std::move(intxn))
290
    {}
533✔
291
    shared_ptr<RecordsDB> db;
292
    MDBRWTransaction txn;
293
  };
294

295
  vector<RecordsDB> d_trecords;
296
  ;
297

298
  std::shared_ptr<MDBROCursor> d_getcursor;
299

300
  shared_ptr<tdomains_t> d_tdomains;
301
  shared_ptr<tmeta_t> d_tmeta;
302
  shared_ptr<tkdb_t> d_tkdb;
303
  shared_ptr<ttsig_t> d_ttsig;
304

305
  shared_ptr<RecordsROTransaction> d_rotxn; // for lookup and list
306
  shared_ptr<RecordsRWTransaction> d_rwtxn; // for feedrecord within begin/aborttransaction
307
  std::shared_ptr<RecordsRWTransaction> getRecordsRWTransaction(uint32_t id);
308
  std::shared_ptr<RecordsROTransaction> getRecordsROTransaction(uint32_t id, const std::shared_ptr<LMDBBackend::RecordsRWTransaction>& rwtxn = nullptr);
309
  int genChangeDomain(const DNSName& domain, const std::function<void(DomainInfo&)>& func);
310
  int genChangeDomain(uint32_t id, const std::function<void(DomainInfo&)>& func);
311
  void deleteDomainRecords(RecordsRWTransaction& txn, uint32_t domain_id, uint16_t qtype = QType::ANY);
312

313
  void getAllDomainsFiltered(vector<DomainInfo>* domains, const std::function<bool(DomainInfo&)>& allow);
314

315
  bool getSerial(DomainInfo& di);
316

317
  bool upgradeToSchemav3();
318

319
  bool get_list(DNSZoneRecord& rr);
320
  bool get_lookup(DNSZoneRecord& rr);
321
  std::string d_matchkey;
322
  DNSName d_lookupdomain;
323

324
  vector<LMDBResourceRecord> d_currentrrset;
325
  size_t d_currentrrsetpos;
326
  MDBOutVal d_currentKey;
327
  MDBOutVal d_currentVal;
328
  bool d_includedisabled;
329

330
  DNSName d_transactiondomain;
331
  uint32_t d_transactiondomainid;
332
  bool d_dolog;
333
  bool d_random_ids;
334
  bool d_handle_dups;
335
  DTime d_dtime; // used only for logging
336
};
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