]> git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/lua-auth.cc
Sphinx 1.8.0 seems broken, use any other version available instead
[thirdparty/pdns.git] / pdns / lua-auth.cc
1 /*
2 * This file is part of PowerDNS or dnsdist.
3 * Copyright -- PowerDNS.COM B.V. and its contributors
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * In addition, for the avoidance of any doubt, permission is granted to
10 * link this program with OpenSSL and to (re)distribute the binaries
11 * produced as the result of such linking.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 */
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25 #include "lua-auth.hh"
26
27 #if !defined(HAVE_LUA)
28
29 AuthLua::AuthLua(const std::string &fname)
30 : PowerDNSLua(fname)
31 {
32 // empty
33 }
34
35 DNSPacket* AuthLua::prequery(DNSPacket *p)
36 {
37 return 0;
38 }
39
40 #else
41
42
43 extern "C" {
44 #undef L
45 /* Include the Lua API header files. */
46 #include <lua.h>
47 #include <lauxlib.h>
48 #include <lualib.h>
49 }
50
51 #include <stdlib.h>
52 #include <stdio.h>
53 #include <string>
54 #include <vector>
55 #include <stdexcept>
56
57 #include "logger.hh"
58 #include "namespaces.hh"
59
60 AuthLua::AuthLua(const std::string &fname)
61 : PowerDNSLua(fname)
62 {
63 registerLuaDNSPacket();
64 pthread_mutex_init(&d_lock,0);
65 }
66
67 struct LuaDNSPacket
68 {
69 DNSPacket *d_p;
70 };
71
72 static DNSPacket* ldp_checkDNSPacket(lua_State *L) {
73 void *ud = luaL_checkudata(L, 1, "LuaDNSPacket");
74 luaL_argcheck(L, ud != NULL, 1, "`LuaDNSPacket' expected");
75 return ((LuaDNSPacket *)ud)->d_p;
76 }
77
78 static int ldp_setRcode(lua_State *L) {
79 DNSPacket *p=ldp_checkDNSPacket(L);
80 #if LUA_VERSION_NUM < 503
81 int rcode = luaL_checkint(L, 2);
82 #else
83 int rcode = (int)luaL_checkinteger(L, 2);
84 #endif
85 p->setRcode(rcode);
86 return 0;
87 }
88
89 static int ldp_getQuestion(lua_State *L) {
90 DNSPacket *p=ldp_checkDNSPacket(L);
91 lua_pushstring(L, p->qdomain.toString().c_str());
92 lua_pushnumber(L, p->qtype.getCode());
93 return 2;
94 }
95
96 static int ldp_getWild(lua_State *L) {
97 DNSPacket *p=ldp_checkDNSPacket(L);
98 if(p->qdomainwild.empty())
99 lua_pushnil(L);
100 else
101 lua_pushstring(L, p->qdomainwild.toString().c_str());
102 return 1;
103 }
104
105 static int ldp_getZone(lua_State *L) {
106 DNSPacket *p=ldp_checkDNSPacket(L);
107 if(p->qdomainzone.empty())
108 lua_pushnil(L);
109 else
110 lua_pushstring(L, p->qdomainzone.toString().c_str());
111 return 1;
112 }
113
114 static int ldp_addRecords(lua_State *L) {
115 DNSPacket *p=ldp_checkDNSPacket(L);
116 vector<DNSRecord> rrs;
117 popResourceRecordsTable(L, DNSName("BOGUS"), rrs);
118 for(const DNSRecord& dr : rrs) {
119 DNSZoneRecord dzr;
120 dzr.dr=dr;
121 dzr.auth=true; // LET'S HOPE THIS IS TRUE XXX
122 p->addRecord(dzr);
123 }
124 return 0;
125 }
126
127 static int ldp_getRemote(lua_State *L) {
128 DNSPacket *p=ldp_checkDNSPacket(L);
129 lua_pushstring(L, p->getRemote().toString().c_str());
130 return 1;
131 }
132
133 static int ldp_getRemoteRaw(lua_State *L) {
134 DNSPacket *p=ldp_checkDNSPacket(L);
135 const ComboAddress& ca=p->getRemote();
136 if(ca.sin4.sin_family == AF_INET) {
137 lua_pushlstring(L, (const char*)&ca.sin4.sin_addr.s_addr, 4);
138 }
139 else {
140 lua_pushlstring(L, (const char*)&ca.sin6.sin6_addr.s6_addr, 16);
141 }
142 return 1;
143 }
144
145 static int ldp_getRcode(lua_State *L) {
146 DNSPacket *p=ldp_checkDNSPacket(L);
147 lua_pushnumber(L, p->d.rcode);
148 return 1;
149 }
150
151 static int ldp_getSize(lua_State *L) {
152 DNSPacket *p=ldp_checkDNSPacket(L);
153 lua_pushnumber(L, p->getString().size());
154 return 1;
155 }
156
157 static int ldp_getRRCounts(lua_State *L) {
158 DNSPacket *p=ldp_checkDNSPacket(L);
159 lua_pushnumber(L, ntohs(p->d.ancount));
160 lua_pushnumber(L, ntohs(p->d.nscount));
161 lua_pushnumber(L, ntohs(p->d.arcount));
162 return 3;
163 }
164
165 // these functions are used for PowerDNS recursor regression testing against auth,
166 // and for the Lua Policy Engine. The Lua 5.2 implementation is untested.
167 static const struct luaL_Reg ldp_methods [] = {
168 {"setRcode", ldp_setRcode},
169 {"getQuestion", ldp_getQuestion},
170 {"getWild", ldp_getWild},
171 {"getZone", ldp_getZone},
172 {"addRecords", ldp_addRecords},
173 {"getRemote", ldp_getRemote},
174 {"getRemoteRaw", ldp_getRemoteRaw},
175 {"getSize", ldp_getSize},
176 {"getRRCounts", ldp_getRRCounts},
177 {"getRcode", ldp_getRcode},
178 {NULL, NULL}
179 };
180
181 #if LUA_VERSION_NUM < 502
182 void AuthLua::registerLuaDNSPacket(void) {
183
184 luaL_newmetatable(d_lua, "LuaDNSPacket");
185
186 lua_pushstring(d_lua, "__index");
187 lua_pushvalue(d_lua, -2); /* pushes the metatable */
188 lua_settable(d_lua, -3); /* metatable.__index = metatable */
189
190 luaL_openlib(d_lua, NULL, ldp_methods, 0);
191
192 lua_pop(d_lua, 1);
193 }
194 #else
195
196 void AuthLua::registerLuaDNSPacket(void) {
197
198 luaL_newmetatable(d_lua, "LuaDNSPacket");
199
200 lua_pushstring(d_lua, "__index");
201 lua_pushvalue(d_lua, -2); /* pushes the metatable */
202 lua_settable(d_lua, -3); /* metatable.__index = metatable */
203
204 luaL_setfuncs(d_lua, ldp_methods, 0);
205
206 lua_pop(d_lua, 1);
207 }
208 #endif
209
210 DNSPacket* AuthLua::prequery(DNSPacket *p)
211 {
212 lua_getglobal(d_lua,"prequery");
213 if(!lua_isfunction(d_lua, -1)) {
214 // cerr<<"No such function 'prequery'\n";
215 lua_pop(d_lua, 1);
216 return 0;
217 }
218
219 DNSPacket *r=0;
220 // allocate a fresh packet and prefill the question
221 r=p->replyPacket();
222
223 // wrap it
224 LuaDNSPacket* lua_dp = (LuaDNSPacket *)lua_newuserdata(d_lua, sizeof(LuaDNSPacket));
225 lua_dp->d_p=r;
226
227 // make it of the right type
228 luaL_getmetatable(d_lua, "LuaDNSPacket");
229 lua_setmetatable(d_lua, -2);
230
231 if(lua_pcall(d_lua, 1, 1, 0)) { // error
232 string error=string("lua error in prequery: ")+lua_tostring(d_lua, -1);
233 theL()<<Logger::Error<<error<<endl;
234
235 lua_pop(d_lua, 1);
236 throw runtime_error(error);
237 }
238 bool res=lua_toboolean(d_lua, 1);
239 lua_pop(d_lua, 1);
240 if(res) {
241 // prequery created our response, use it
242 theL()<<Logger::Info<<"overriding query from lua prequery result"<<endl;
243 return r;
244 }
245 else
246 {
247 // prequery wanted nothing to do with this question
248 delete r;
249 return 0;
250 }
251 }
252
253 #endif