]>
git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/lua-auth4.cc
1 #include "lua-auth4.hh"
2 #include "stubresolver.hh"
5 #include "dnsparser.hh"
6 #include "namespaces.hh"
7 #include "ednssubnet.hh"
8 #include <unordered_set>
10 #if !defined(HAVE_LUA)
12 AuthLua4::AuthLua4(const std::string
& fname
) { }
13 bool AuthLua4::updatePolicy(const DNSName
&qname
, QType qtype
, const DNSName
&zonename
, DNSPacket
*packet
) { return false; }
14 bool AuthLua4::axfrfilter(const ComboAddress
& remote
, const DNSName
& zone
, const DNSResourceRecord
& in
, vector
<DNSResourceRecord
>& out
) { return false; }
15 AuthLua4::~AuthLua4() { }
20 #include "ext/luawrapper/include/LuaContext.hpp"
22 AuthLua4::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
); });
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==);
45 d_lw
->registerFunction("__eq", &DNSResourceRecord::operator==);
46 d_lw
->registerFunction("__lt", &DNSResourceRecord::operator<);
48 d_lw
->registerFunction
<string(DNSResourceRecord::*)()>("toString", [](const DNSResourceRecord
& rec
) { return rec
.getZoneRepresentation();} );
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
; });
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
; });
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);
71 return string((const char*)&ca
.sin6
.sin6_addr
.s6_addr
, 16);
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(); });
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
)
83 if(auto s
= boost::get
<string
>(&in
)) {
84 cas
.insert(ComboAddress(*s
));
86 else if(auto v
= boost::get
<vector
<pair
<unsigned int, string
> > >(&in
)) {
87 for(const auto& str
: *v
)
88 cas
.insert(ComboAddress(str
.second
));
91 cas
.insert(boost::get
<ComboAddress
>(in
));
93 catch(std::exception
& e
) { theL() <<Logger::Error
<<e
.what()<<endl
; }
96 d_lw
->registerFunction
<bool(cas_t::*)(const ComboAddress
&)>("check",[](const cas_t
& cas
, const ComboAddress
&ca
) {
97 return (bool)cas
.count(ca
);
102 d_lw
->registerFunction
<bool(ComboAddress::*)(const ComboAddress
&)>("equal", [](const ComboAddress
& lhs
, const ComboAddress
& rhs
) {
103 return ComboAddress::addressOnlyEqual()(lhs
, rhs
);
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
);
111 d_lw
->writeFunction("newNMG", []() { return NetmaskGroup(); });
112 d_lw
->registerFunction
<void(NetmaskGroup::*)(const std::string
&mask
)>("addMask", [](NetmaskGroup
&nmg
, const std::string
& mask
)
117 d_lw
->registerFunction
<void(NetmaskGroup::*)(const vector
<pair
<unsigned int, std::string
>>&)>("addMasks", [](NetmaskGroup
&nmg
, const vector
<pair
<unsigned int, std::string
>>& masks
)
119 for(const auto& mask
: masks
)
120 nmg
.addMask(mask
.second
);
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
);
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
;
137 if(auto rec
= std::dynamic_pointer_cast
<ARecordContent
>(dr
.d_content
))
139 else if(auto aaaarec
= std::dynamic_pointer_cast
<AAAARecordContent
>(dr
.d_content
))
140 ret
=aaaarec
->getCA(53);
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
); });
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
;
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
}
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
});
170 pd
.push_back({"place", in_t
{
177 pd
.push_back({"loglevels", in_t
{
178 {"Alert", LOG_ALERT
},
179 {"Critical", LOG_CRIT
},
180 {"Debug", LOG_DEBUG
},
181 {"Emergency", LOG_EMERG
},
183 {"Notice", LOG_NOTICE
},
184 {"Warning", LOG_WARNING
},
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
);
193 d_lw
->writeVariable("pdns", pd
);
195 d_lw
->writeFunction("resolve", [](const std::string
& qname
, uint16_t qtype
) {
196 std::vector
<DNSZoneRecord
> ret
;
197 std::unordered_map
<int, DNSResourceRecord
> luaResult
;
198 stubDoResolve(DNSName(qname
), qtype
, ret
);
200 for(const auto &row
: ret
) {
201 luaResult
[++i
] = DNSResourceRecord::fromWire(row
.dr
);
202 luaResult
[i
].auth
= row
.auth
;
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 */
221 theL()<<Logger::Error
<<"Unable to read configuration file from '"<<fname
<<"': "<<strerror(errno
)<<endl
;
224 d_lw
->executeCode(ifs
);
226 d_update_policy
= d_lw
->readVariable
<boost::optional
<luacall_update_policy_t
>>("updatepolicy").get_value_or(0);
227 d_axfr_filter
= d_lw
->readVariable
<boost::optional
<luacall_axfr_filter_t
>>("axfrfilter").get_value_or(0);
231 bool AuthLua4::axfrfilter(const ComboAddress
& remote
, const DNSName
& zone
, const DNSResourceRecord
& in
, vector
<DNSResourceRecord
>& out
) {
232 luacall_axfr_filter_t::result_type ret
;
235 if (d_axfr_filter
== NULL
) return false;
237 ret
= d_axfr_filter(remote
, zone
, in
);
238 rcode
= std::get
<0>(ret
);
244 throw PDNSException("Cannot understand return code "+std::to_string(rcode
)+" in axfr filter response");
246 const auto& rows
= std::get
<1>(ret
);
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")
254 rec
.qname
= DNSName(boost::get
<std::string
>(col
.second
)).makeLowerCase();
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
));
260 throw PDNSException("Cannot understand "+col
.first
+" in axfr filter response on row "+std::to_string(row
.first
));
269 bool AuthLua4::updatePolicy(const DNSName
&qname
, QType qtype
, const DNSName
&zonename
, DNSPacket
*packet
) {
270 UpdatePolicyQuery upq
;
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
;
280 return d_update_policy(upq
);
283 AuthLua4::~AuthLua4() { }