• 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

50.66
/pdns/lua-auth4.cc
1
#include "config.h"
2
#include "ext/luawrapper/include/LuaContext.hpp"
3
#include "lua-auth4.hh"
4
#include "stubresolver.hh"
5
#include <fstream>
6
#include "logger.hh"
7
#include "dnsparser.hh"
8
#include "namespaces.hh"
9
#include "ednssubnet.hh"
10
#include <unordered_set>
11
#include "sstuff.hh"
12
#include <thread>
13

14
#include "ueberbackend.hh"
15

16
LuaContext* AuthLua4::getLua()
17
{
×
18
  return d_lw.get();
×
19
}
×
20

21
void AuthLua4::postPrepareContext() {
2✔
22
  d_lw->writeFunction("resolve", [](const std::string& qname, uint16_t qtype) {
2✔
23
      std::vector<DNSZoneRecord> ret;
×
24
      std::unordered_map<int, DNSResourceRecord> luaResult;
×
25
      stubDoResolve(DNSName(qname), qtype, ret);
×
26
      int i = 0;
×
27
      for(const auto &row: ret) {
×
28
        luaResult[++i] = DNSResourceRecord::fromWire(row.dr);
×
29
        luaResult[i].auth = row.auth;
×
30
      }
×
31
      return luaResult;
×
32
  });
×
33

34
/* DNSPacket */
35
  d_lw->writeFunction("newDNSPacket", [](bool isQuery) { return std::make_shared<DNSPacket>(isQuery); });
2✔
36
  d_lw->writeFunction("dupDNSPacket", [](const std::shared_ptr<DNSPacket> &orig) { return std::make_shared<DNSPacket>(*orig); });
2✔
37
  d_lw->registerFunction<DNSPacket, int(const char *, size_t)>("noparse", [](DNSPacket &p, const char *mesg, size_t len){ return p.noparse(mesg, len); });
2✔
38
  d_lw->registerFunction<DNSPacket, int(const char *, size_t)>("parse", [](DNSPacket &p, const char *mesg, size_t len){ return p.parse(mesg, len); });
2✔
39
  d_lw->registerFunction<DNSPacket, const std::string()>("getString", [](DNSPacket &p) { return p.getString(); });
2✔
40
  d_lw->registerFunction<DNSPacket, void(const ComboAddress&)>("setRemote", [](DNSPacket &p, const ComboAddress &ca) { p.setRemote(&ca); });
2✔
41
  d_lw->registerFunction<DNSPacket, ComboAddress()>("getRemote", [](DNSPacket &p) { return p.getInnerRemote(); });
2✔
42
  d_lw->registerFunction<DNSPacket, Netmask()>("getRealRemote", [](DNSPacket &p) { return p.getRealRemote(); });
2✔
43
  d_lw->registerFunction<DNSPacket, ComboAddress()>("getLocal", [](DNSPacket &p) { return p.getLocal(); });
2✔
44
  d_lw->registerFunction<DNSPacket, unsigned int()>("getRemotePort", [](DNSPacket &p) { return p.getInnerRemote().getPort(); });
2✔
45
  d_lw->registerFunction<DNSPacket, std::tuple<const std::string, unsigned int>()>("getQuestion", [](DNSPacket &p) { return std::tuple(p.qdomain.toString(), static_cast<unsigned int>(p.qtype.getCode())); });
2✔
46
  d_lw->registerFunction<DNSPacket, void(bool)>("setA", [](DNSPacket &p, bool a) { return p.setA(a); });
2✔
47
  d_lw->registerFunction<DNSPacket, void(unsigned int)>("setID", [](DNSPacket &p, unsigned int id) { return p.setID(static_cast<uint16_t>(id)); });
2✔
48
  d_lw->registerFunction<DNSPacket, void(bool)>("setRA", [](DNSPacket &p, bool ra) { return p.setRA(ra); });
2✔
49
  d_lw->registerFunction<DNSPacket, void(bool)>("setRD", [](DNSPacket &p, bool rd) { return p.setRD(rd); });
2✔
50
  d_lw->registerFunction<DNSPacket, void(bool)>("setAnswer", [](DNSPacket &p, bool answer) { return p.setAnswer(answer); });
2✔
51
  d_lw->registerFunction<DNSPacket, void(unsigned int)>("setOpCode", [](DNSPacket &p, unsigned int opcode) { return p.setOpcode(static_cast<uint16_t>(opcode)); });
2✔
52
  d_lw->registerFunction<DNSPacket, void(int)>("setRcode", [](DNSPacket &p, int rcode) { return p.setRcode(rcode); });
2✔
53
  d_lw->registerFunction<DNSPacket, void()>("clearRecords",[](DNSPacket &p){p.clearRecords();});
2✔
54
  d_lw->registerFunction<DNSPacket, void(DNSRecord&, bool)>("addRecord", [](DNSPacket &p, DNSRecord &dr, bool auth) { DNSZoneRecord dzr; dzr.dr = dr; dzr.auth = auth; p.addRecord(std::move(dzr)); });
2✔
55
  d_lw->registerFunction<DNSPacket, void(const vector<pair<unsigned int, DNSRecord> >&)>("addRecords", [](DNSPacket &p, const vector<pair<unsigned int, DNSRecord> >& records){ for(const auto &dr: records){ DNSZoneRecord dzr; dzr.dr = std::get<1>(dr); dzr.auth = true; p.addRecord(std::move(dzr)); }});
2!
56
  d_lw->registerFunction<DNSPacket, void(unsigned int, const DNSName&, const std::string&)>("setQuestion", [](DNSPacket &p, unsigned int opcode, const DNSName &name, const string &type){ QType qtype; qtype = type; p.setQuestion(static_cast<int>(opcode), name, static_cast<int>(qtype.getCode())); });
2✔
57
  d_lw->registerFunction<DNSPacket, bool()>("isEmpty", [](DNSPacket &p){return p.isEmpty();});
2✔
58
  d_lw->registerFunction<DNSPacket, std::shared_ptr<DNSPacket>()>("replyPacket",[](DNSPacket& p){ return p.replyPacket();});
2✔
59
  d_lw->registerFunction<DNSPacket, bool()>("hasEDNSSubnet", [](DNSPacket &p){return p.hasEDNSSubnet();});
2✔
60
  d_lw->registerFunction<DNSPacket, bool()>("hasEDNS",[](DNSPacket &p){return p.hasEDNS();});
2✔
61
  d_lw->registerFunction<DNSPacket, unsigned int()>("getEDNSVersion",[](DNSPacket &p){return p.getEDNSVersion();});
2✔
62
  d_lw->registerFunction<DNSPacket, void(unsigned int)>("setEDNSRcode",[](DNSPacket &p, unsigned int extRCode){p.setEDNSRcode(static_cast<uint16_t>(extRCode));});
2✔
63
  d_lw->registerFunction<DNSPacket, unsigned int()>("getEDNSRcode",[](DNSPacket &p){return p.getEDNSRCode();});
2✔
64
  d_lw->registerFunction<DNSPacket, DNSName()>("getTSIGKeyname",[](DNSPacket &p){ return p.getTSIGKeyname();});
2✔
65
  d_lw->registerFunction<DNSPacket, std::unordered_map<unsigned int, DNSRecord>()>("getRRS", [](DNSPacket &p){ std::unordered_map<unsigned int, DNSRecord> ret; unsigned int i = 0; for(const auto &rec: p.getRRS()) { ret.insert({i++, rec.dr}); } return ret;});
2!
66
  d_lw->registerMember<DNSPacket, DNSName>("qdomain", [](const DNSPacket &p) -> DNSName { return p.qdomain; }, [](DNSPacket &p, const DNSName& name) { p.qdomain = name; });
2✔
67
  d_lw->registerMember<DNSPacket, DNSName>("qdomainwild", [](const DNSPacket &p) -> DNSName { return p.qdomainwild; }, [](DNSPacket &p, const DNSName& name) { p.qdomainwild = name; });
2✔
68
  d_lw->registerMember<DNSPacket, DNSName>("qdomainzone", [](const DNSPacket &p) -> DNSName { return p.qdomainzone; }, [](DNSPacket &p, const DNSName& name) { p.qdomainzone = name; });
2✔
69

70
  d_lw->registerMember<DNSPacket, std::string>("d_peer_principal", [](const DNSPacket &p) -> std::string { return p.d_peer_principal; }, [](DNSPacket &p, const std::string &princ) { p.d_peer_principal = princ; });
2✔
71
  d_lw->registerMember<DNSPacket, const std::string>("qtype", [](const DNSPacket &p) ->  const std::string { return p.qtype.toString(); }, [](DNSPacket &p, const std::string &type) { p.qtype = type; });
2✔
72
/* End of DNSPacket */
73

74

75
/* update policy */
76
  d_lw->registerFunction<DNSName(UpdatePolicyQuery::*)()>("getQName", [](UpdatePolicyQuery& upq) { return upq.qname; });
2✔
77
  d_lw->registerFunction<DNSName(UpdatePolicyQuery::*)()>("getZoneName", [](UpdatePolicyQuery& upq) { return upq.zonename; });
2✔
78
  d_lw->registerFunction<uint16_t(UpdatePolicyQuery::*)()>("getQType", [](UpdatePolicyQuery& upq) { return upq.qtype; });
2✔
79
  d_lw->registerFunction<ComboAddress(UpdatePolicyQuery::*)()>("getLocal", [](UpdatePolicyQuery& upq) { return upq.local; });
2✔
80
  d_lw->registerFunction<ComboAddress(UpdatePolicyQuery::*)()>("getRemote", [](UpdatePolicyQuery& upq) { return upq.remote; });
2✔
81
  d_lw->registerFunction<Netmask(UpdatePolicyQuery::*)()>("getRealRemote", [](UpdatePolicyQuery& upq) { return upq.realRemote; });
2✔
82
  d_lw->registerFunction<DNSName(UpdatePolicyQuery::*)()>("getTsigName", [](UpdatePolicyQuery& upq) { return upq.tsigName; });
2✔
83
  d_lw->registerFunction<std::string(UpdatePolicyQuery::*)()>("getPeerPrincipal", [](UpdatePolicyQuery& upq) { return upq.peerPrincipal; });
3✔
84
/* end of update policy */
85
  if (!d_include_path.empty()) {
2!
86
    includePath(d_include_path);
×
87
  }
×
88
}
2✔
89

90
void AuthLua4::postLoad() {
2✔
91
  d_update_policy = d_lw->readVariable<boost::optional<luacall_update_policy_t>>("updatepolicy").get_value_or(nullptr);
2✔
92
  d_axfr_filter = d_lw->readVariable<boost::optional<luacall_axfr_filter_t>>("axfrfilter").get_value_or(nullptr);
2✔
93
  d_prequery = d_lw->readVariable<boost::optional<luacall_prequery_t>>("prequery").get_value_or(nullptr);
2✔
94
}
2✔
95

96
bool AuthLua4::axfrfilter(const ComboAddress& remote, const DNSName& zone, const DNSResourceRecord& in, vector<DNSResourceRecord>& out) {
×
97
  if (!d_axfr_filter) {
×
98
    return false;
×
99
  }
×
100

101
  const auto& [rcode, rows] = d_axfr_filter(remote, zone, in);
×
102
  if (rcode < 0) {
×
103
    // no modification, handle normally
104
    return false;
×
105
  }
×
106
  else if (rcode == 0) {
×
107
    // replace the matching record by the filtered record(s)
108
  }
×
109
  else if (rcode == 1) {
×
110
    // append the filtered record(s) after the matching record
111
    out.push_back(in);
×
112
  }
×
113
  else
×
114
    throw PDNSException("Cannot understand return code "+std::to_string(rcode)+" in axfr filter response");
×
115

116
  try {
×
117
    for(const auto& row: rows) {
×
118
      DNSResourceRecord rec;
×
119

120
      const auto& map = row.second;
×
121
      rec.qtype = QType(boost::get<unsigned int>(map.at("qtype")));
×
122
      rec.qname = DNSName(boost::get<std::string>(map.at("qname")));
×
123
      rec.qname.makeUsLowerCase();
×
124
      if (map.count("ttl")) {
×
125
        rec.ttl = boost::get<unsigned int>(map.at("ttl"));
×
126
      }
×
127
      rec.setContent(boost::get<std::string>(map.at("content")));
×
128

129
      out.push_back(rec);
×
130
    }
×
131
  }
×
132
  catch (const std::exception& e) {
×
133
    throw PDNSException("Cannot understand axfr filter response: " + std::string(e.what()));
×
134
  }
×
135
  catch (const PDNSException& e) {
×
136
    throw PDNSException("Cannot understand axfr filter response: " + e.reason);
×
137
  }
×
138

139
  return true;
×
140
}
×
141

142

143
bool AuthLua4::updatePolicy(const DNSName &qname, const QType& qtype, const DNSName &zonename, const DNSPacket& packet) {
3✔
144
  // default decision is all goes
145
  if (d_update_policy == nullptr) return true;
3!
146

147
  UpdatePolicyQuery upq;
3✔
148
  upq.qname = qname;
3✔
149
  upq.qtype = qtype.getCode();
3✔
150
  upq.zonename = zonename;
3✔
151
  upq.local = packet.getLocal();
3✔
152
  upq.remote = packet.getInnerRemote();
3✔
153
  upq.realRemote = packet.getRealRemote();
3✔
154
  upq.tsigName = packet.getTSIGKeyname();
3✔
155
  upq.peerPrincipal = packet.d_peer_principal;
3✔
156

157
  return d_update_policy(upq);
3✔
158
}
3✔
159

160
std::unique_ptr<DNSPacket> AuthLua4::prequery(const DNSPacket& q) {
1✔
161
  if (d_prequery == nullptr) return nullptr;
1!
162

163
  auto r = q.replyPacket();
1✔
164
  if (d_prequery(r.get()))
1!
165
    return r;
1✔
166

167
  return nullptr;
×
168
}
1✔
169

170
AuthLua4::~AuthLua4() = default;
2✔
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