[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: luasocket sandbox
- From: Leo Leo <leo4mailing@...>
- Date: Tue, 7 Feb 2006 23:44:11 +0100
In fact I have solved my problem (in Lua). I store the tcp socket in an upvalue table with his index only stored in the sandbox table for the socket. Then I have redefined socket.select() to take the wrapper index, take the real socket in the upvalue, call select() and re-wrapping the results in the sandbox. That way, my tcp socket are always in their sandbox table and the Lua socket protocol don't need to be changed.
2006/2/7, Leo Leo <leo4mailing@gmail.com>:
Hi,
I want to write a software that execute lua networking code. My goal was to
sandbox Luasocket to put restrictions on what hosts are allowed or not,
maximum amout of bandwith, number of sockets opened, ... Initially, I thinked
that I could easily do that in pure lua using closure. But after a
promising start, wrapping socket objects into an array, I discover a major
problem, the socket.select() function. This function cannot take my array
and need 'pure' socket to use them. So, now, I have implemented that the
listen() and connect() method return a pure socket rather than an array.
That break the Luasocket protocol and permit only to put restriction on
hosts but no other ones like bandwith management.
Do you think there is a good (and secure) solution in Lua or I must do some
change in C ? If I must change C, where and how do you advise me to change
to be as clean as possible ? Some of you as already a socket sandbox ready
? :-)
Thank you, reguards.
Leo
PS: Here is my socket sandbox code:
do
local s_ori = socket
socket = {}
-- socket.tcp() is originally a 'master' object, transformed in 'server'
-- object by a call to listen() or transformed in a 'client' object by a call
-- to connect(). At this point select() need an array of 'client' or
-- 'server' objects. So after a call to listen() or connect(), we must
-- return a new object because we can't change our object wrapper (array) in
-- the final object. This way break lightly the luasocket syntax. Anyway,
-- this solution permit only host filtering and not socket and bandwith
-- limitations. One more problem is that you can normally use a 'master'
-- object in select but not in this solution, because 'master' object is
-- always wrapped in a table.
socket.tcp = function()
local stcp = s_ori.tcp()
local sock = {}
-- We must break the protocol here, because socket.select() need pure
-- socket{client|master} objects and no tables.
sock.connect = function(self, host, ...)
if host ~= "this.denied.host" then
local s, msg = stcp.connect(stcp, host, unpack(arg))
if s ~= nil then
return stcp
else
return s, msg
end
else
return nil, "sandbox"
end
end
-- We must break the protocol here, because
socket.select() need pure
-- socket{client|master} objects and no tables.
sock.listen = function(self, ...)
local s = stcp.listen(stcp, unpack(arg))
if s == nil then
return nil
else
return stcp
end
end
sock.bind = function(self, ...)
return stcp.bind(stcp, unpack(arg))
end
sock.close = function(self, ...)
return stcp.close(stcp, unpack(arg))
end
sock.getsockname = function(self, ...)
return stcp.getsockname(stcp, unpack(arg))
end
sock.getstats = function(self, ...)
return
stcp.getstats(stcp, unpack(arg))
end
sock.setstats = function(self, ...)
return stcp.setstats(stcp, unpack(arg))
end
sock.settimeout
= function(self, ...)
return stcp.settimeout(stcp, unpack(arg))
end
-- metatable (didn't work ..., not important implemented above)
--[[
local sock_meta = {}
sock_meta['__index'] = function (table, func)
return stcp[func]
end
sock_meta['__newindex'] = function (table, func) end
setmetatable(sock, sock_meta)
]]--
return sock
end
socket.udp = function()
local sudp = s_ori.udp()
local sock = {}
sock.close = function(self, ...)
return sudp.close(sudp, unpack(arg))
end
sock.getpeername = function(self, ...)
return sudp.getpeername(sudp, unpack(arg))
end
sock.getsockname = function(self, ...)
return sudp.getsockname(sudp, unpack(arg))
end
sock.receive = function(self, ...)
return
sudp.receive(sudp, unpack(arg))
end
sock.receivefrom = function(self, ...)
return sudp.receivefrom(sudp, unpack(arg))
end
sock.send = function(self, ...)
return sudp.send(sudp, unpack(arg))
end
sock.sendto = function(self, ...)
return sudp.sendto(sudp, unpack(arg))
end
sock.setpeername = function(self, ...)
return sudp.setpeername(sudp, unpack(arg))
end
sock.setsockname = function(self, ...)
return sudp.setsockname(sudp, unpack(arg))
end
sock.setoption = function(self, ...)
return sudp.setoption(sudp, unpack(arg))
end
sock.settimeout = function(self, ...)
return sudp.settimeout(sudp, unpack(arg))
end
return sock
end
socket.bind = function(...)
return s_ori.bind(unpack(arg))
end
socket.connect = function(...)
return s_ori.connect(unpack(arg))
end
socket._DEBUG = s_ori._DEBUG
socket.newtry = function(...)
return s_ori.newtry(unpack(arg))
end
socket.protect = function(...)
return s_ori.protect(unpack(arg))
end
socket.select = function(...)
return s_ori.select(unpack(arg))
end
socket.sink = function(...)
return s_ori.sink(unpack(arg))
end
socket.skip
= function(...)
return s_ori.skip(unpack(arg))
end
socket.sleep = function(...)
return s_ori.sleep(unpack(arg))
end
socket.source = function(...)
return s_ori.source(unpack(arg))
end
socket.gettime = function(...)
return s_ori.gettime(unpack(arg))
end
socket.try = function(...)
return s_ori.try(unpack(arg))
end
socket._VERSION = s_ori._VERSION
socket.dns = {}
socket.dns.gethostname = function(...)
return s_ori.dns.gethostname(unpack(arg))
end
socket.dns.tohostname = function(...)
return s_ori.dns.tohostname(unpack(arg))
end
socket.dns.toip = function(...)
return s_ori.dns.toip(unpack(arg))
end
end