]>
git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/lua-auth4.cc
3 #include "ext/luawrapper/include/LuaContext.hpp"
5 #include "lua-auth4.hh"
6 #include "stubresolver.hh"
9 #include "dnsparser.hh"
10 #include "namespaces.hh"
11 #include "ednssubnet.hh"
12 #include <unordered_set>
17 #include "ueberbackend.hh"
19 #if !defined(HAVE_LUA)
21 AuthLua4::AuthLua4(const std::string
& fname
) { }
22 bool AuthLua4::updatePolicy(const DNSName
&qname
, QType qtype
, const DNSName
&zonename
, DNSPacket
*packet
) { return false; }
23 bool AuthLua4::axfrfilter(const ComboAddress
& remote
, const DNSName
& zone
, const DNSResourceRecord
& in
, vector
<DNSResourceRecord
>& out
) { return false; }
24 LuaContext
* AuthLua4::getLua() { return 0; }
25 AuthLua4::~AuthLua4() { }
29 LuaContext
* AuthLua4::getLua()
34 AuthLua4::AuthLua4(const std::string
& fname
) {
35 d_lw
= std::unique_ptr
<LuaContext
>(new LuaContext
);
36 stubParseResolveConf();
37 d_lw
->registerFunction
<int(dnsheader::*)()>("getID", [](dnsheader
& dh
) { return dh
.id
; });
38 d_lw
->registerFunction
<bool(dnsheader::*)()>("getCD", [](dnsheader
& dh
) { return dh
.cd
; });
39 d_lw
->registerFunction
<bool(dnsheader::*)()>("getTC", [](dnsheader
& dh
) { return dh
.tc
; });
40 d_lw
->registerFunction
<bool(dnsheader::*)()>("getRA", [](dnsheader
& dh
) { return dh
.ra
; });
41 d_lw
->registerFunction
<bool(dnsheader::*)()>("getAD", [](dnsheader
& dh
) { return dh
.ad
; });
42 d_lw
->registerFunction
<bool(dnsheader::*)()>("getAA", [](dnsheader
& dh
) { return dh
.aa
; });
43 d_lw
->registerFunction
<bool(dnsheader::*)()>("getRD", [](dnsheader
& dh
) { return dh
.rd
; });
44 d_lw
->registerFunction
<int(dnsheader::*)()>("getRCODE", [](dnsheader
& dh
) { return dh
.rcode
; });
45 d_lw
->registerFunction
<int(dnsheader::*)()>("getOPCODE", [](dnsheader
& dh
) { return dh
.opcode
; });
46 d_lw
->registerFunction
<int(dnsheader::*)()>("getQDCOUNT", [](dnsheader
& dh
) { return ntohs(dh
.qdcount
); });
47 d_lw
->registerFunction
<int(dnsheader::*)()>("getANCOUNT", [](dnsheader
& dh
) { return ntohs(dh
.ancount
); });
48 d_lw
->registerFunction
<int(dnsheader::*)()>("getNSCOUNT", [](dnsheader
& dh
) { return ntohs(dh
.nscount
); });
49 d_lw
->registerFunction
<int(dnsheader::*)()>("getARCOUNT", [](dnsheader
& dh
) { return ntohs(dh
.arcount
); });
51 d_lw
->writeFunction("newDN", [](const std::string
& dom
){ return DNSName(dom
); });
52 d_lw
->registerFunction("isPartOf", &DNSName::isPartOf
);
53 d_lw
->registerFunction
<bool(DNSName::*)(const std::string
&)>("equal",
54 [](const DNSName
& lhs
, const std::string
& rhs
) { return lhs
==DNSName(rhs
); });
55 d_lw
->registerFunction("__eq", &DNSName::operator==);
57 d_lw
->registerFunction("__eq", &DNSResourceRecord::operator==);
58 d_lw
->registerFunction("__lt", &DNSResourceRecord::operator<);
60 d_lw
->registerFunction
<string(DNSResourceRecord::*)()>("toString", [](const DNSResourceRecord
& rec
) { return rec
.getZoneRepresentation();} );
62 d_lw
->registerFunction
<DNSName(DNSResourceRecord::*)()>("qname", [](DNSResourceRecord
& rec
) { return rec
.qname
; });
63 d_lw
->registerFunction
<DNSName(DNSResourceRecord::*)()>("wildcardname", [](DNSResourceRecord
& rec
) { return rec
.wildcardname
; });
64 d_lw
->registerFunction
<string(DNSResourceRecord::*)()>("content", [](DNSResourceRecord
& rec
) { return rec
.content
; });
65 d_lw
->registerFunction
<time_t(DNSResourceRecord::*)()>("last_modified", [](DNSResourceRecord
& rec
) { return rec
.last_modified
; });
66 d_lw
->registerFunction
<uint32_t(DNSResourceRecord::*)()>("ttl", [](DNSResourceRecord
& rec
) { return rec
.ttl
; });
67 d_lw
->registerFunction
<uint32_t(DNSResourceRecord::*)()>("signttl", [](DNSResourceRecord
& rec
) { return rec
.signttl
; });
68 d_lw
->registerFunction
<int(DNSResourceRecord::*)()>("domain_id", [](DNSResourceRecord
& rec
) { return rec
.domain_id
; });
69 d_lw
->registerFunction
<uint16_t(DNSResourceRecord::*)()>("qtype", [](DNSResourceRecord
& rec
) { return rec
.qtype
.getCode(); });
70 d_lw
->registerFunction
<uint16_t(DNSResourceRecord::*)()>("qclass", [](DNSResourceRecord
& rec
) { return rec
.qclass
; });
71 d_lw
->registerFunction
<uint8_t(DNSResourceRecord::*)()>("scopeMask", [](DNSResourceRecord
& rec
) { return rec
.scopeMask
; });
72 d_lw
->registerFunction
<bool(DNSResourceRecord::*)()>("auth", [](DNSResourceRecord
& rec
) { return rec
.auth
; });
73 d_lw
->registerFunction
<bool(DNSResourceRecord::*)()>("disabled", [](DNSResourceRecord
& rec
) { return rec
.disabled
; });
75 d_lw
->registerFunction
<string(ComboAddress::*)()>("toString", [](const ComboAddress
& ca
) { return ca
.toString(); });
76 d_lw
->registerFunction
<string(ComboAddress::*)()>("toStringWithPort", [](const ComboAddress
& ca
) { return ca
.toStringWithPort(); });
77 d_lw
->registerFunction
<uint16_t(ComboAddress::*)()>("getPort", [](const ComboAddress
& ca
) { return ntohs(ca
.sin4
.sin_port
); } );
78 d_lw
->registerFunction
<string(ComboAddress::*)()>("getRaw", [](const ComboAddress
& ca
) {
79 if(ca
.sin4
.sin_family
== AF_INET
) {
80 auto t
=ca
.sin4
.sin_addr
.s_addr
; return string((const char*)&t
, 4);
83 return string((const char*)&ca
.sin6
.sin6_addr
.s6_addr
, 16);
86 d_lw
->writeFunction("newCA", [](const std::string
& a
) { return ComboAddress(a
); });
87 typedef std::unordered_set
<ComboAddress
,ComboAddress::addressOnlyHash
,ComboAddress::addressOnlyEqual
> cas_t
;
88 d_lw
->writeFunction("newCAS", []{ return cas_t(); });
91 d_lw
->registerFunction
<void(cas_t::*)(boost::variant
<string
,ComboAddress
, vector
<pair
<unsigned int,string
> > >)>("add",
92 [](cas_t
& cas
, const boost::variant
<string
,ComboAddress
,vector
<pair
<unsigned int,string
> > >& in
)
95 if(auto s
= boost::get
<string
>(&in
)) {
96 cas
.insert(ComboAddress(*s
));
98 else if(auto v
= boost::get
<vector
<pair
<unsigned int, string
> > >(&in
)) {
99 for(const auto& str
: *v
)
100 cas
.insert(ComboAddress(str
.second
));
103 cas
.insert(boost::get
<ComboAddress
>(in
));
105 catch(std::exception
& e
) { theL() <<Logger::Error
<<e
.what()<<endl
; }
108 d_lw
->registerFunction
<bool(cas_t::*)(const ComboAddress
&)>("check",[](const cas_t
& cas
, const ComboAddress
&ca
) {
109 return (bool)cas
.count(ca
);
114 d_lw
->registerFunction
<bool(ComboAddress::*)(const ComboAddress
&)>("equal", [](const ComboAddress
& lhs
, const ComboAddress
& rhs
) {
115 return ComboAddress::addressOnlyEqual()(lhs
, rhs
);
119 d_lw
->registerFunction
<ComboAddress(Netmask::*)()>("getNetwork", [](const Netmask
& nm
) { return nm
.getNetwork(); } ); // const reference makes this necessary
120 d_lw
->registerFunction("toString", &Netmask::toString
);
121 d_lw
->registerFunction("empty", &Netmask::empty
);
123 d_lw
->writeFunction("newNMG", []() { return NetmaskGroup(); });
124 d_lw
->registerFunction
<void(NetmaskGroup::*)(const std::string
&mask
)>("addMask", [](NetmaskGroup
&nmg
, const std::string
& mask
)
129 d_lw
->registerFunction
<void(NetmaskGroup::*)(const vector
<pair
<unsigned int, std::string
>>&)>("addMasks", [](NetmaskGroup
&nmg
, const vector
<pair
<unsigned int, std::string
>>& masks
)
131 for(const auto& mask
: masks
)
132 nmg
.addMask(mask
.second
);
136 d_lw
->registerFunction("match", (bool (NetmaskGroup::*)(const ComboAddress
&) const)&NetmaskGroup::match
);
137 d_lw
->registerFunction
<string(DNSName::*)()>("toString", [](const DNSName
&dn
) { return dn
.toString(); });
138 d_lw
->registerFunction
<string(DNSName::*)()>("toStringNoDot", [](const DNSName
&dn
) { return dn
.toStringNoDot(); });
139 d_lw
->registerFunction
<bool(DNSName::*)()>("chopOff", [](DNSName
&dn
) { return dn
.chopOff(); });
140 d_lw
->registerMember("name", &DNSRecord::d_name
);
141 d_lw
->registerMember("type", &DNSRecord::d_type
);
142 d_lw
->registerMember("ttl", &DNSRecord::d_ttl
);
145 d_lw
->registerFunction
<string(DNSRecord::*)()>("getContent", [](const DNSRecord
& dr
) { return dr
.d_content
->getZoneRepresentation(); });
146 d_lw
->registerFunction
<boost::optional
<ComboAddress
>(DNSRecord::*)()>("getCA", [](const DNSRecord
& dr
) {
147 boost::optional
<ComboAddress
> ret
;
149 if(auto rec
= std::dynamic_pointer_cast
<ARecordContent
>(dr
.d_content
))
151 else if(auto aaaarec
= std::dynamic_pointer_cast
<AAAARecordContent
>(dr
.d_content
))
152 ret
=aaaarec
->getCA(53);
157 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
); });
159 d_lw
->writeFunction("pdnslog", [](const std::string
& msg
, boost::optional
<int> loglevel
) {
160 theL() << (Logger::Urgency
)loglevel
.get_value_or(Logger::Warning
) << msg
<<endl
;
162 typedef vector
<pair
<string
, int> > in_t
;
163 vector
<pair
<string
, boost::variant
<int, in_t
, struct timeval
* > > > pd
{
164 {"PASS", (int)PolicyDecision::PASS
}, {"DROP", (int)PolicyDecision::DROP
},
165 {"TRUNCATE", (int)PolicyDecision::TRUNCATE
}
168 vector
<pair
<string
, int> > rcodes
= {{"NOERROR", RCode::NoError
},
169 {"FORMERR", RCode::FormErr
},
170 {"SERVFAIL", RCode::ServFail
},
171 {"NXDOMAIN", RCode::NXDomain
},
172 {"NOTIMP", RCode::NotImp
},
173 {"REFUSED", RCode::Refused
},
174 {"YXDOMAIN", RCode::YXDomain
},
175 {"YXRRSET", RCode::YXRRSet
},
176 {"NXRRSET", RCode::NXRRSet
},
177 {"NOTAUTH", RCode::NotAuth
},
178 {"NOTZONE", RCode::NotZone
}};
179 for(const auto& rcode
: rcodes
)
180 pd
.push_back({rcode
.first
, rcode
.second
});
182 pd
.push_back({"place", in_t
{
189 pd
.push_back({"loglevels", in_t
{
190 {"Alert", LOG_ALERT
},
191 {"Critical", LOG_CRIT
},
192 {"Debug", LOG_DEBUG
},
193 {"Emergency", LOG_EMERG
},
195 {"Notice", LOG_NOTICE
},
196 {"Warning", LOG_WARNING
},
200 for(const auto& n
: QType::names
)
201 pd
.push_back({n
.first
, n
.second
});
202 d_lw
->registerMember("tv_sec", &timeval::tv_sec
);
203 d_lw
->registerMember("tv_usec", &timeval::tv_usec
);
205 d_lw
->writeVariable("pdns", pd
);
207 d_lw
->writeFunction("resolve", [](const std::string
& qname
, uint16_t qtype
) {
208 std::vector
<DNSZoneRecord
> ret
;
209 std::unordered_map
<int, DNSResourceRecord
> luaResult
;
210 stubDoResolve(DNSName(qname
), qtype
, ret
);
212 for(const auto &row
: ret
) {
213 luaResult
[++i
] = DNSResourceRecord::fromWire(row
.dr
);
214 luaResult
[i
].auth
= row
.auth
;
221 d_lw
->registerFunction
<DNSName(UpdatePolicyQuery::*)()>("getQName", [](UpdatePolicyQuery
& upq
) { return upq
.qname
; });
222 d_lw
->registerFunction
<DNSName(UpdatePolicyQuery::*)()>("getZoneName", [](UpdatePolicyQuery
& upq
) { return upq
.zonename
; });
223 d_lw
->registerFunction
<uint16_t(UpdatePolicyQuery::*)()>("getQType", [](UpdatePolicyQuery
& upq
) { return upq
.qtype
; });
224 d_lw
->registerFunction
<ComboAddress(UpdatePolicyQuery::*)()>("getLocal", [](UpdatePolicyQuery
& upq
) { return upq
.local
; });
225 d_lw
->registerFunction
<ComboAddress(UpdatePolicyQuery::*)()>("getRemote", [](UpdatePolicyQuery
& upq
) { return upq
.remote
; });
226 d_lw
->registerFunction
<Netmask(UpdatePolicyQuery::*)()>("getRealRemote", [](UpdatePolicyQuery
& upq
) { return upq
.realRemote
; });
227 d_lw
->registerFunction
<DNSName(UpdatePolicyQuery::*)()>("getTsigName", [](UpdatePolicyQuery
& upq
) { return upq
.tsigName
; });
228 d_lw
->registerFunction
<std::string(UpdatePolicyQuery::*)()>("getPeerPrincipal", [](UpdatePolicyQuery
& upq
) { return upq
.peerPrincipal
; });
229 /* end of update policy */
234 theL()<<Logger::Error
<<"Unable to read configuration file from '"<<fname
<<"': "<<strerror(errno
)<<endl
;
237 d_lw
->executeCode(ifs
);
239 d_update_policy
= d_lw
->readVariable
<boost::optional
<luacall_update_policy_t
>>("updatepolicy").get_value_or(0);
240 d_axfr_filter
= d_lw
->readVariable
<boost::optional
<luacall_axfr_filter_t
>>("axfrfilter").get_value_or(0);
245 bool AuthLua4::axfrfilter(const ComboAddress
& remote
, const DNSName
& zone
, const DNSResourceRecord
& in
, vector
<DNSResourceRecord
>& out
) {
246 luacall_axfr_filter_t::result_type ret
;
249 if (d_axfr_filter
== NULL
) return false;
251 ret
= d_axfr_filter(remote
, zone
, in
);
252 rcode
= std::get
<0>(ret
);
258 throw PDNSException("Cannot understand return code "+std::to_string(rcode
)+" in axfr filter response");
260 const auto& rows
= std::get
<1>(ret
);
262 for(const auto& row
: rows
) {
263 DNSResourceRecord rec
;
264 for(const auto& col
: row
.second
) {
265 if (col
.first
== "qtype")
266 rec
.qtype
= QType(boost::get
<unsigned int>(col
.second
));
267 else if (col
.first
== "qname")
268 rec
.qname
= DNSName(boost::get
<std::string
>(col
.second
)).makeLowerCase();
269 else if (col
.first
== "ttl")
270 rec
.ttl
= boost::get
<unsigned int>(col
.second
);
271 else if (col
.first
== "content")
272 rec
.setContent(boost::get
<std::string
>(col
.second
));
274 throw PDNSException("Cannot understand "+col
.first
+" in axfr filter response on row "+std::to_string(row
.first
));
283 bool AuthLua4::updatePolicy(const DNSName
&qname
, QType qtype
, const DNSName
&zonename
, DNSPacket
*packet
) {
284 UpdatePolicyQuery upq
;
286 upq
.qtype
= qtype
.getCode();
287 upq
.zonename
= zonename
;
288 upq
.local
= packet
->getLocal();
289 upq
.remote
= packet
->getRemote();
290 upq
.realRemote
= packet
->getRealRemote();
291 upq
.tsigName
= packet
->getTSIGKeyname();
292 upq
.peerPrincipal
= packet
->d_peer_principal
;
294 return d_update_policy(upq
);
297 AuthLua4::~AuthLua4() { }