]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/lua-auth4.cc
Sphinx 1.8.0 seems broken, use any other version available instead
[thirdparty/pdns.git] / pdns / lua-auth4.cc
CommitLineData
0ecc1158
AT
1#include "lua-auth4.hh"
2#include "stubresolver.hh"
3#include <fstream>
4#include "logger.hh"
5#include "dnsparser.hh"
0ecc1158 6#include "namespaces.hh"
0ecc1158
AT
7#include "ednssubnet.hh"
8#include <unordered_set>
9
10#if !defined(HAVE_LUA)
11
12AuthLua4::AuthLua4(const std::string& fname) { }
13bool AuthLua4::updatePolicy(const DNSName &qname, QType qtype, const DNSName &zonename, DNSPacket *packet) { return false; }
66470601 14bool AuthLua4::axfrfilter(const ComboAddress& remote, const DNSName& zone, const DNSResourceRecord& in, vector<DNSResourceRecord>& out) { return false; }
3ce6361c 15AuthLua4::~AuthLua4() { }
0ecc1158
AT
16
17#else
18
19#undef L
20#include "ext/luawrapper/include/LuaContext.hpp"
21
22AuthLua4::AuthLua4(const std::string& fname) {
23 d_lw = std::unique_ptr<LuaContext>(new LuaContext);
24 stubParseResolveConf();
25 d_lw->registerFunction<int(dnsheader::*)()>("getID", [](dnsheader& dh) { return dh.id; });
26 d_lw->registerFunction<bool(dnsheader::*)()>("getCD", [](dnsheader& dh) { return dh.cd; });
27 d_lw->registerFunction<bool(dnsheader::*)()>("getTC", [](dnsheader& dh) { return dh.tc; });
28 d_lw->registerFunction<bool(dnsheader::*)()>("getRA", [](dnsheader& dh) { return dh.ra; });
29 d_lw->registerFunction<bool(dnsheader::*)()>("getAD", [](dnsheader& dh) { return dh.ad; });
30 d_lw->registerFunction<bool(dnsheader::*)()>("getAA", [](dnsheader& dh) { return dh.aa; });
31 d_lw->registerFunction<bool(dnsheader::*)()>("getRD", [](dnsheader& dh) { return dh.rd; });
32 d_lw->registerFunction<int(dnsheader::*)()>("getRCODE", [](dnsheader& dh) { return dh.rcode; });
33 d_lw->registerFunction<int(dnsheader::*)()>("getOPCODE", [](dnsheader& dh) { return dh.opcode; });
34 d_lw->registerFunction<int(dnsheader::*)()>("getQDCOUNT", [](dnsheader& dh) { return ntohs(dh.qdcount); });
35 d_lw->registerFunction<int(dnsheader::*)()>("getANCOUNT", [](dnsheader& dh) { return ntohs(dh.ancount); });
36 d_lw->registerFunction<int(dnsheader::*)()>("getNSCOUNT", [](dnsheader& dh) { return ntohs(dh.nscount); });
37 d_lw->registerFunction<int(dnsheader::*)()>("getARCOUNT", [](dnsheader& dh) { return ntohs(dh.arcount); });
38
39 d_lw->writeFunction("newDN", [](const std::string& dom){ return DNSName(dom); });
40 d_lw->registerFunction("isPartOf", &DNSName::isPartOf);
41 d_lw->registerFunction<bool(DNSName::*)(const std::string&)>("equal",
42 [](const DNSName& lhs, const std::string& rhs) { return lhs==DNSName(rhs); });
43 d_lw->registerFunction("__eq", &DNSName::operator==);
44
45 d_lw->registerFunction("__eq", &DNSResourceRecord::operator==);
46 d_lw->registerFunction("__lt", &DNSResourceRecord::operator<);
47
48 d_lw->registerFunction<string(DNSResourceRecord::*)()>("toString", [](const DNSResourceRecord& rec) { return rec.getZoneRepresentation();} );
49
50 d_lw->registerFunction<DNSName(DNSResourceRecord::*)()>("qname", [](DNSResourceRecord& rec) { return rec.qname; });
51 d_lw->registerFunction<DNSName(DNSResourceRecord::*)()>("wildcardname", [](DNSResourceRecord& rec) { return rec.wildcardname; });
52 d_lw->registerFunction<string(DNSResourceRecord::*)()>("content", [](DNSResourceRecord& rec) { return rec.content; });
53 d_lw->registerFunction<time_t(DNSResourceRecord::*)()>("last_modified", [](DNSResourceRecord& rec) { return rec.last_modified; });
54 d_lw->registerFunction<uint32_t(DNSResourceRecord::*)()>("ttl", [](DNSResourceRecord& rec) { return rec.ttl; });
55 d_lw->registerFunction<uint32_t(DNSResourceRecord::*)()>("signttl", [](DNSResourceRecord& rec) { return rec.signttl; });
56 d_lw->registerFunction<int(DNSResourceRecord::*)()>("domain_id", [](DNSResourceRecord& rec) { return rec.domain_id; });
57 d_lw->registerFunction<uint16_t(DNSResourceRecord::*)()>("qtype", [](DNSResourceRecord& rec) { return rec.qtype.getCode(); });
58 d_lw->registerFunction<uint16_t(DNSResourceRecord::*)()>("qclass", [](DNSResourceRecord& rec) { return rec.qclass; });
0ecc1158
AT
59 d_lw->registerFunction<uint8_t(DNSResourceRecord::*)()>("scopeMask", [](DNSResourceRecord& rec) { return rec.scopeMask; });
60 d_lw->registerFunction<bool(DNSResourceRecord::*)()>("auth", [](DNSResourceRecord& rec) { return rec.auth; });
61 d_lw->registerFunction<bool(DNSResourceRecord::*)()>("disabled", [](DNSResourceRecord& rec) { return rec.disabled; });
62
63 d_lw->registerFunction<string(ComboAddress::*)()>("toString", [](const ComboAddress& ca) { return ca.toString(); });
64 d_lw->registerFunction<string(ComboAddress::*)()>("toStringWithPort", [](const ComboAddress& ca) { return ca.toStringWithPort(); });
65 d_lw->registerFunction<uint16_t(ComboAddress::*)()>("getPort", [](const ComboAddress& ca) { return ntohs(ca.sin4.sin_port); } );
66 d_lw->registerFunction<string(ComboAddress::*)()>("getRaw", [](const ComboAddress& ca) {
67 if(ca.sin4.sin_family == AF_INET) {
68 auto t=ca.sin4.sin_addr.s_addr; return string((const char*)&t, 4);
69 }
70 else
71 return string((const char*)&ca.sin6.sin6_addr.s6_addr, 16);
72 } );
73
74 d_lw->writeFunction("newCA", [](const std::string& a) { return ComboAddress(a); });
75 typedef std::unordered_set<ComboAddress,ComboAddress::addressOnlyHash,ComboAddress::addressOnlyEqual> cas_t;
76 d_lw->writeFunction("newCAS", []{ return cas_t(); });
77
78
79 d_lw->registerFunction<void(cas_t::*)(boost::variant<string,ComboAddress, vector<pair<unsigned int,string> > >)>("add",
80 [](cas_t& cas, const boost::variant<string,ComboAddress,vector<pair<unsigned int,string> > >& in)
81 {
82 try {
83 if(auto s = boost::get<string>(&in)) {
84 cas.insert(ComboAddress(*s));
85 }
86 else if(auto v = boost::get<vector<pair<unsigned int, string> > >(&in)) {
2010ac95
RG
87 for(const auto& str : *v)
88 cas.insert(ComboAddress(str.second));
0ecc1158
AT
89 }
90 else
91 cas.insert(boost::get<ComboAddress>(in));
92 }
93 catch(std::exception& e) { theL() <<Logger::Error<<e.what()<<endl; }
94 });
95
96 d_lw->registerFunction<bool(cas_t::*)(const ComboAddress&)>("check",[](const cas_t& cas, const ComboAddress&ca) {
97 return (bool)cas.count(ca);
98 });
99
100
101
102 d_lw->registerFunction<bool(ComboAddress::*)(const ComboAddress&)>("equal", [](const ComboAddress& lhs, const ComboAddress& rhs) {
103 return ComboAddress::addressOnlyEqual()(lhs, rhs);
104 });
105
106
107 d_lw->registerFunction<ComboAddress(Netmask::*)()>("getNetwork", [](const Netmask& nm) { return nm.getNetwork(); } ); // const reference makes this necessary
108 d_lw->registerFunction("toString", &Netmask::toString);
109 d_lw->registerFunction("empty", &Netmask::empty);
110
111 d_lw->writeFunction("newNMG", []() { return NetmaskGroup(); });
112 d_lw->registerFunction<void(NetmaskGroup::*)(const std::string&mask)>("addMask", [](NetmaskGroup&nmg, const std::string& mask)
113 {
114 nmg.addMask(mask);
115 });
116
117 d_lw->registerFunction<void(NetmaskGroup::*)(const vector<pair<unsigned int, std::string>>&)>("addMasks", [](NetmaskGroup&nmg, const vector<pair<unsigned int, std::string>>& masks)
118 {
119 for(const auto& mask: masks)
120 nmg.addMask(mask.second);
121 });
122
123
124 d_lw->registerFunction("match", (bool (NetmaskGroup::*)(const ComboAddress&) const)&NetmaskGroup::match);
125 d_lw->registerFunction<string(DNSName::*)()>("toString", [](const DNSName&dn ) { return dn.toString(); });
126 d_lw->registerFunction<string(DNSName::*)()>("toStringNoDot", [](const DNSName&dn ) { return dn.toStringNoDot(); });
127 d_lw->registerFunction<bool(DNSName::*)()>("chopOff", [](DNSName&dn ) { return dn.chopOff(); });
128 d_lw->registerMember("name", &DNSRecord::d_name);
129 d_lw->registerMember("type", &DNSRecord::d_type);
130 d_lw->registerMember("ttl", &DNSRecord::d_ttl);
131
132
133 d_lw->registerFunction<string(DNSRecord::*)()>("getContent", [](const DNSRecord& dr) { return dr.d_content->getZoneRepresentation(); });
134 d_lw->registerFunction<boost::optional<ComboAddress>(DNSRecord::*)()>("getCA", [](const DNSRecord& dr) {
135 boost::optional<ComboAddress> ret;
136
137 if(auto rec = std::dynamic_pointer_cast<ARecordContent>(dr.d_content))
138 ret=rec->getCA(53);
2010ac95
RG
139 else if(auto aaaarec = std::dynamic_pointer_cast<AAAARecordContent>(dr.d_content))
140 ret=aaaarec->getCA(53);
0ecc1158
AT
141 return ret;
142 });
143
144
6177a176 145 d_lw->registerFunction<void(DNSRecord::*)(const std::string&)>("changeContent", [](DNSRecord& dr, const std::string& newContent) { dr.d_content = DNSRecordContent::mastermake(dr.d_type, 1, newContent); });
0ecc1158
AT
146
147 d_lw->writeFunction("pdnslog", [](const std::string& msg, boost::optional<int> loglevel) {
148 theL() << (Logger::Urgency)loglevel.get_value_or(Logger::Warning) << msg<<endl;
149 });
150 typedef vector<pair<string, int> > in_t;
151 vector<pair<string, boost::variant<int, in_t, struct timeval* > > > pd{
152 {"PASS", (int)PolicyDecision::PASS}, {"DROP", (int)PolicyDecision::DROP},
153 {"TRUNCATE", (int)PolicyDecision::TRUNCATE}
154 };
155
156 vector<pair<string, int> > rcodes = {{"NOERROR", RCode::NoError },
157 {"FORMERR", RCode::FormErr },
158 {"SERVFAIL", RCode::ServFail },
159 {"NXDOMAIN", RCode::NXDomain },
160 {"NOTIMP", RCode::NotImp },
161 {"REFUSED", RCode::Refused },
162 {"YXDOMAIN", RCode::YXDomain },
163 {"YXRRSET", RCode::YXRRSet },
164 {"NXRRSET", RCode::NXRRSet },
165 {"NOTAUTH", RCode::NotAuth },
166 {"NOTZONE", RCode::NotZone }};
167 for(const auto& rcode : rcodes)
168 pd.push_back({rcode.first, rcode.second});
169
170 pd.push_back({"place", in_t{
171 {"QUESTION", 0},
172 {"ANSWER", 1},
173 {"AUTHORITY", 2},
174 {"ADDITIONAL", 3}
175 }});
176
177 pd.push_back({"loglevels", in_t{
178 {"Alert", LOG_ALERT},
179 {"Critical", LOG_CRIT},
180 {"Debug", LOG_DEBUG},
181 {"Emergency", LOG_EMERG},
182 {"Info", LOG_INFO},
183 {"Notice", LOG_NOTICE},
184 {"Warning", LOG_WARNING},
185 {"Error", LOG_ERR}
186 }});
187
188 for(const auto& n : QType::names)
189 pd.push_back({n.first, n.second});
190 d_lw->registerMember("tv_sec", &timeval::tv_sec);
191 d_lw->registerMember("tv_usec", &timeval::tv_usec);
192
193 d_lw->writeVariable("pdns", pd);
194
195 d_lw->writeFunction("resolve", [](const std::string& qname, uint16_t qtype) {
7e683fad 196 std::vector<DNSZoneRecord> ret;
0ecc1158 197 std::unordered_map<int, DNSResourceRecord> luaResult;
7e683fad 198 stubDoResolve(DNSName(qname), qtype, ret);
0ecc1158 199 int i = 0;
7e683fad 200 for(const auto &row: ret) {
6b04b4ad 201 luaResult[++i] = DNSResourceRecord::fromWire(row.dr);
7e683fad 202 luaResult[i].auth = row.auth;
203 }
0ecc1158
AT
204 return luaResult;
205 });
206
66470601 207
0ecc1158
AT
208/* update policy */
209 d_lw->registerFunction<DNSName(UpdatePolicyQuery::*)()>("getQName", [](UpdatePolicyQuery& upq) { return upq.qname; });
210 d_lw->registerFunction<DNSName(UpdatePolicyQuery::*)()>("getZoneName", [](UpdatePolicyQuery& upq) { return upq.zonename; });
211 d_lw->registerFunction<uint16_t(UpdatePolicyQuery::*)()>("getQType", [](UpdatePolicyQuery& upq) { return upq.qtype; });
212 d_lw->registerFunction<ComboAddress(UpdatePolicyQuery::*)()>("getLocal", [](UpdatePolicyQuery& upq) { return upq.local; });
213 d_lw->registerFunction<ComboAddress(UpdatePolicyQuery::*)()>("getRemote", [](UpdatePolicyQuery& upq) { return upq.remote; });
214 d_lw->registerFunction<Netmask(UpdatePolicyQuery::*)()>("getRealRemote", [](UpdatePolicyQuery& upq) { return upq.realRemote; });
215 d_lw->registerFunction<DNSName(UpdatePolicyQuery::*)()>("getTsigName", [](UpdatePolicyQuery& upq) { return upq.tsigName; });
216 d_lw->registerFunction<std::string(UpdatePolicyQuery::*)()>("getPeerPrincipal", [](UpdatePolicyQuery& upq) { return upq.peerPrincipal; });
217/* end of update policy */
218
219 ifstream ifs(fname);
220 if(!ifs) {
221 theL()<<Logger::Error<<"Unable to read configuration file from '"<<fname<<"': "<<strerror(errno)<<endl;
222 return;
223 }
224 d_lw->executeCode(ifs);
225
226 d_update_policy = d_lw->readVariable<boost::optional<luacall_update_policy_t>>("updatepolicy").get_value_or(0);
66470601
AT
227 d_axfr_filter = d_lw->readVariable<boost::optional<luacall_axfr_filter_t>>("axfrfilter").get_value_or(0);
228
229}
230
231bool AuthLua4::axfrfilter(const ComboAddress& remote, const DNSName& zone, const DNSResourceRecord& in, vector<DNSResourceRecord>& out) {
232 luacall_axfr_filter_t::result_type ret;
233 int rcode;
234
235 if (d_axfr_filter == NULL) return false;
236
237 ret = d_axfr_filter(remote, zone, in);
238 rcode = std::get<0>(ret);
239 if (rcode < 0)
240 return false;
241 else if (rcode == 1)
242 out.push_back(in);
243 else
244 throw PDNSException("Cannot understand return code "+std::to_string(rcode)+" in axfr filter response");
245
246 const auto& rows = std::get<1>(ret);
247
248 for(const auto& row: rows) {
249 DNSResourceRecord rec;
250 for(const auto& col: row.second) {
251 if (col.first == "qtype")
252 rec.qtype = QType(boost::get<unsigned int>(col.second));
253 else if (col.first == "qname")
92c6c467 254 rec.qname = DNSName(boost::get<std::string>(col.second)).makeLowerCase();
66470601
AT
255 else if (col.first == "ttl")
256 rec.ttl = boost::get<unsigned int>(col.second);
257 else if (col.first == "content")
258 rec.setContent(boost::get<std::string>(col.second));
259 else
260 throw PDNSException("Cannot understand "+col.first+" in axfr filter response on row "+std::to_string(row.first));
261 }
262 out.push_back(rec);
263 }
264
265 return true;
0ecc1158
AT
266}
267
66470601 268
0ecc1158
AT
269bool AuthLua4::updatePolicy(const DNSName &qname, QType qtype, const DNSName &zonename, DNSPacket *packet) {
270 UpdatePolicyQuery upq;
271 upq.qname = qname;
272 upq.qtype = qtype.getCode();
273 upq.zonename = zonename;
274 upq.local = packet->getLocal();
275 upq.remote = packet->getRemote();
276 upq.realRemote = packet->getRealRemote();
277 upq.tsigName = packet->getTSIGKeyname();
278 upq.peerPrincipal = packet->d_peer_principal;
279
280 return d_update_policy(upq);
281}
282
3ce6361c
RG
283AuthLua4::~AuthLua4() { }
284
0ecc1158 285#endif