]> git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/lua-auth4.cc
rec: ensure correct service user on debian
[thirdparty/pdns.git] / pdns / lua-auth4.cc
1 #include "config.h"
2 #if defined(HAVE_LUA)
3 #include "ext/luawrapper/include/LuaContext.hpp"
4 #endif
5 #include "lua-auth4.hh"
6 #include "stubresolver.hh"
7 #include <fstream>
8 #include "logger.hh"
9 #include "dnsparser.hh"
10 #include "namespaces.hh"
11 #include "ednssubnet.hh"
12 #include <unordered_set>
13 #include "sstuff.hh"
14 #include <thread>
15 #include <mutex>
16
17 #include "ueberbackend.hh"
18
19 AuthLua4::AuthLua4() { prepareContext(); }
20
21 #if !defined(HAVE_LUA)
22
23 bool AuthLua4::updatePolicy(const DNSName &qname, QType qtype, const DNSName &zonename, DNSPacket *packet) { return false; }
24 bool AuthLua4::axfrfilter(const ComboAddress& remote, const DNSName& zone, const DNSResourceRecord& in, vector<DNSResourceRecord>& out) { return false; }
25 LuaContext* AuthLua4::getLua() { return 0; }
26 DNSPacket *AuthLua4::prequery(DNSPacket *q) { return NULL; }
27
28 AuthLua4::~AuthLua4() { }
29
30 void AuthLua4::postPrepareContext()
31 {
32 }
33
34 void AuthLua4::postLoad()
35 {
36 }
37
38 #else
39
40 LuaContext* AuthLua4::getLua()
41 {
42 return d_lw.get();
43 }
44
45 void AuthLua4::postPrepareContext() {
46 d_lw->writeFunction("resolve", [](const std::string& qname, uint16_t qtype) {
47 std::vector<DNSZoneRecord> ret;
48 std::unordered_map<int, DNSResourceRecord> luaResult;
49 stubDoResolve(DNSName(qname), qtype, ret);
50 int i = 0;
51 for(const auto &row: ret) {
52 luaResult[++i] = DNSResourceRecord::fromWire(row.dr);
53 luaResult[i].auth = row.auth;
54 }
55 return luaResult;
56 });
57
58 /* DNSPacket */
59 d_lw->writeFunction("newDNSPacket", [](bool isQuery) { return new DNSPacket(isQuery); });
60 d_lw->writeFunction("dupDNSPacket", [](const DNSPacket &orig) { return new DNSPacket(orig); });
61 d_lw->registerFunction<DNSPacket, int(const char *, size_t)>("noparse", [](DNSPacket &p, const char *mesg, size_t len){ return p.noparse(mesg, len); });
62 d_lw->registerFunction<DNSPacket, int(const char *, size_t)>("parse", [](DNSPacket &p, const char *mesg, size_t len){ return p.parse(mesg, len); });
63 d_lw->registerFunction<DNSPacket, const std::string()>("getString", [](DNSPacket &p) { return p.getString(); });
64 d_lw->registerFunction<DNSPacket, void(const ComboAddress&)>("setRemote", [](DNSPacket &p, const ComboAddress &ca) { p.setRemote(&ca); });
65 d_lw->registerFunction<DNSPacket, ComboAddress()>("getRemote", [](DNSPacket &p) { return p.getRemote(); });
66 d_lw->registerFunction<DNSPacket, Netmask()>("getRealRemote", [](DNSPacket &p) { return p.getRealRemote(); });
67 d_lw->registerFunction<DNSPacket, ComboAddress()>("getLocal", [](DNSPacket &p) { return p.getLocal(); });
68 d_lw->registerFunction<DNSPacket, unsigned int()>("getRemotePort", [](DNSPacket &p) { return p.getRemotePort(); });
69 d_lw->registerFunction<DNSPacket, std::tuple<const std::string, unsigned int>()>("getQuestion", [](DNSPacket &p) { return std::make_tuple(p.qdomain.toString(), static_cast<unsigned int>(p.qtype.getCode())); });
70 d_lw->registerFunction<DNSPacket, void(bool)>("setA", [](DNSPacket &p, bool a) { return p.setA(a); });
71 d_lw->registerFunction<DNSPacket, void(unsigned int)>("setID", [](DNSPacket &p, unsigned int id) { return p.setID(static_cast<uint16_t>(id)); });
72 d_lw->registerFunction<DNSPacket, void(bool)>("setRA", [](DNSPacket &p, bool ra) { return p.setRA(ra); });
73 d_lw->registerFunction<DNSPacket, void(bool)>("setRD", [](DNSPacket &p, bool rd) { return p.setRD(rd); });
74 d_lw->registerFunction<DNSPacket, void(bool)>("setAnswer", [](DNSPacket &p, bool answer) { return p.setAnswer(answer); });
75 d_lw->registerFunction<DNSPacket, void(unsigned int)>("setOpCode", [](DNSPacket &p, unsigned int opcode) { return p.setOpcode(static_cast<uint16_t>(opcode)); });
76 d_lw->registerFunction<DNSPacket, void(int)>("setRcode", [](DNSPacket &p, int rcode) { return p.setRcode(rcode); });
77 d_lw->registerFunction<DNSPacket, void()>("clearRecords",[](DNSPacket &p){p.clearRecords();});
78 d_lw->registerFunction<DNSPacket, void(DNSRecord&, bool)>("addRecord", [](DNSPacket &p, DNSRecord &dr, bool auth) { DNSZoneRecord dzr; dzr.dr = dr; dzr.auth = auth; p.addRecord(dzr); });
79 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(dzr); }});
80 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())); });
81 d_lw->registerFunction<DNSPacket, bool()>("isEmpty", [](DNSPacket &p){return p.isEmpty();});
82 d_lw->registerFunction<DNSPacket, DNSPacket*()>("replyPacket",[](DNSPacket& p){ return p.replyPacket();});
83 d_lw->registerFunction<DNSPacket, bool()>("hasEDNSSubnet", [](DNSPacket &p){return p.hasEDNSSubnet();});
84 d_lw->registerFunction<DNSPacket, bool()>("hasEDNS",[](DNSPacket &p){return p.hasEDNS();});
85 d_lw->registerFunction<DNSPacket, unsigned int()>("getEDNSVersion",[](DNSPacket &p){return p.getEDNSVersion();});
86 d_lw->registerFunction<DNSPacket, void(unsigned int)>("setEDNSRcode",[](DNSPacket &p, unsigned int extRCode){p.setEDNSRcode(static_cast<uint16_t>(extRCode));});
87 d_lw->registerFunction<DNSPacket, unsigned int()>("getEDNSRcode",[](DNSPacket &p){return p.getEDNSRCode();});
88 d_lw->registerFunction<DNSPacket, DNSName()>("getTSIGKeyname",[](DNSPacket &p){ return p.getTSIGKeyname();});
89 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;});
90 d_lw->registerMember<DNSPacket, DNSName>("qdomain", [](const DNSPacket &p) -> DNSName { return p.qdomain; }, [](DNSPacket &p, const DNSName& name) { p.qdomain = name; });
91 d_lw->registerMember<DNSPacket, DNSName>("qdomainwild", [](const DNSPacket &p) -> DNSName { return p.qdomainwild; }, [](DNSPacket &p, const DNSName& name) { p.qdomainwild = name; });
92 d_lw->registerMember<DNSPacket, DNSName>("qdomainzone", [](const DNSPacket &p) -> DNSName { return p.qdomainzone; }, [](DNSPacket &p, const DNSName& name) { p.qdomainzone = name; });
93
94 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; });
95 d_lw->registerMember<DNSPacket, const std::string>("qtype", [](const DNSPacket &p) -> const std::string { return p.qtype.getName(); }, [](DNSPacket &p, const std::string &type) { p.qtype = type; });
96 /* End of DNSPacket */
97
98
99 /* update policy */
100 d_lw->registerFunction<DNSName(UpdatePolicyQuery::*)()>("getQName", [](UpdatePolicyQuery& upq) { return upq.qname; });
101 d_lw->registerFunction<DNSName(UpdatePolicyQuery::*)()>("getZoneName", [](UpdatePolicyQuery& upq) { return upq.zonename; });
102 d_lw->registerFunction<uint16_t(UpdatePolicyQuery::*)()>("getQType", [](UpdatePolicyQuery& upq) { return upq.qtype; });
103 d_lw->registerFunction<ComboAddress(UpdatePolicyQuery::*)()>("getLocal", [](UpdatePolicyQuery& upq) { return upq.local; });
104 d_lw->registerFunction<ComboAddress(UpdatePolicyQuery::*)()>("getRemote", [](UpdatePolicyQuery& upq) { return upq.remote; });
105 d_lw->registerFunction<Netmask(UpdatePolicyQuery::*)()>("getRealRemote", [](UpdatePolicyQuery& upq) { return upq.realRemote; });
106 d_lw->registerFunction<DNSName(UpdatePolicyQuery::*)()>("getTsigName", [](UpdatePolicyQuery& upq) { return upq.tsigName; });
107 d_lw->registerFunction<std::string(UpdatePolicyQuery::*)()>("getPeerPrincipal", [](UpdatePolicyQuery& upq) { return upq.peerPrincipal; });
108 /* end of update policy */
109 }
110
111 void AuthLua4::postLoad() {
112 d_update_policy = d_lw->readVariable<boost::optional<luacall_update_policy_t>>("updatepolicy").get_value_or(0);
113 d_axfr_filter = d_lw->readVariable<boost::optional<luacall_axfr_filter_t>>("axfrfilter").get_value_or(0);
114 d_prequery = d_lw->readVariable<boost::optional<luacall_prequery_t>>("prequery").get_value_or(0);
115 }
116
117 bool AuthLua4::axfrfilter(const ComboAddress& remote, const DNSName& zone, const DNSResourceRecord& in, vector<DNSResourceRecord>& out) {
118 luacall_axfr_filter_t::result_type ret;
119 int rcode;
120
121 if (d_axfr_filter == NULL) return false;
122
123 ret = d_axfr_filter(remote, zone, in);
124 rcode = std::get<0>(ret);
125 if (rcode < 0) {
126 // no modification, handle normally
127 return false;
128 }
129 else if (rcode == 0) {
130 // replace the matching record by the filtered record(s)
131 }
132 else if (rcode == 1) {
133 // append the filtered record(s) after the matching record
134 out.push_back(in);
135 }
136 else
137 throw PDNSException("Cannot understand return code "+std::to_string(rcode)+" in axfr filter response");
138
139 const auto& rows = std::get<1>(ret);
140
141 for(const auto& row: rows) {
142 DNSResourceRecord rec;
143 for(const auto& col: row.second) {
144 if (col.first == "qtype")
145 rec.qtype = QType(boost::get<unsigned int>(col.second));
146 else if (col.first == "qname")
147 rec.qname = DNSName(boost::get<std::string>(col.second)).makeLowerCase();
148 else if (col.first == "ttl")
149 rec.ttl = boost::get<unsigned int>(col.second);
150 else if (col.first == "content")
151 rec.setContent(boost::get<std::string>(col.second));
152 else
153 throw PDNSException("Cannot understand "+col.first+" in axfr filter response on row "+std::to_string(row.first));
154 }
155 out.push_back(rec);
156 }
157
158 return true;
159 }
160
161
162 bool AuthLua4::updatePolicy(const DNSName &qname, QType qtype, const DNSName &zonename, DNSPacket *packet) {
163 // default decision is all goes
164 if (d_update_policy == NULL) return true;
165
166 UpdatePolicyQuery upq;
167 upq.qname = qname;
168 upq.qtype = qtype.getCode();
169 upq.zonename = zonename;
170 upq.local = packet->getLocal();
171 upq.remote = packet->getRemote();
172 upq.realRemote = packet->getRealRemote();
173 upq.tsigName = packet->getTSIGKeyname();
174 upq.peerPrincipal = packet->d_peer_principal;
175
176 return d_update_policy(upq);
177 }
178
179 DNSPacket *AuthLua4::prequery(DNSPacket *q) {
180 if (d_prequery == NULL) return NULL;
181
182 DNSPacket *r = q->replyPacket();
183 if (d_prequery(r))
184 return r;
185 delete r;
186 return NULL;
187 }
188
189 AuthLua4::~AuthLua4() { }
190
191
192 #endif