diff --git a/RPC/OpenOS/usr/lib/rpc.lua b/RPC/OpenOS/usr/lib/rpc.lua index 3813b78..31f734d 100644 --- a/RPC/OpenOS/usr/lib/rpc.lua +++ b/RPC/OpenOS/usr/lib/rpc.lua @@ -6,6 +6,7 @@ local rpcf = {} local rpcrunning = false local rpc = {} rpc.port = 111 + function rpc.call(hostname,fn,...) if hostname == "localhost" then return rpcf[fn](...) @@ -39,19 +40,37 @@ function rpc.proxy(hostname,filter) return rt end +local function setacl(self, fname, host) + self[fname] = self[fname] or {} + self[fname][host] = true +end +rpc.allow = setmetatable({},{__call=setacl}) +rpc.deny = setmetatable({},{__call=setacl}) + +local function isPermitted(host,fn) + if rpc.allow[fn] then + return rpc.allow[fn][host] or false + end + if rpc.deny[fn] and rpc.deny[fn][host] then + return false + end + return true +end + function rpc.register(name,fn) if not rpcrunning then event.listen("net_msg",function(_, from, port, data) if port == rpc.port then local rpcrq = serial.unserialize(data) local rpcn, rpcid = table.remove(rpcrq,1), table.remove(rpcrq,1) - if rpcf[rpcn] then + if rpcf[rpcn] and isPermitted(from,rpcn) then local rt = {pcall(rpcf[rpcn],table.unpack(rpcrq))} if rt[1] == true then table.remove(rt,1) end minitel.send(from,port,serial.serialize({rpcid,table.unpack(rt)})) else + minitel.send(from,port,serial.serialize({rpcid,false,"function unavailable"})) end end end) @@ -67,5 +86,4 @@ function rpc.register(name,fn) rpcf[name] = fn end - return rpc diff --git a/RPC/OpenOS/usr/man/rpc b/RPC/OpenOS/usr/man/rpc index e33b22e..9725ec8 100644 --- a/RPC/OpenOS/usr/man/rpc +++ b/RPC/OpenOS/usr/man/rpc @@ -1,5 +1,5 @@ # RPC -Minitel Remote Procedure Call Library +Minitel Remote Procedure Call Library for OpenOS ## API In all instances, if *hostname* is replaced with *localhost*, an attempt will be made to call the registered procedure on the local machine. @@ -13,7 +13,23 @@ Return a table containing the functions on *hostname* matching *filter*, which i ### rpc.register(*name*, *function*) Registers *function* as the RPC call for *name* on the current host. +### rpc.allow(*fname*, *hostname*) +Adds *hostname* to the list of remote hosts allowed to execute the function *fname*. + +## Access control +Access control is implemented by way of an "allow" list and a "deny" list. Any function lacking both lists will default to the function being available to all hosts. + +Any entries in the 'allow' list for a function will disable access for any but those in the allow list. + +Entries in the 'deny' list will result in the hosts in said list being denied, but other hosts are allowed. This will not override the 'allow' list. + ## Variables ### rpc.port = 111 Port to use for RPC calls and registration. + +### rpc.allow = {} +Table containing the allow lists of exported functions. Contents subject to change. + +### rpc.deny = {} +Table containing the deny lists of exported functions. Contents subject to change.