luci-mod-rpc: more auth/login fixes, expose further libraries
[project/luci.git] / modules / luci-mod-rpc / luasrc / controller / rpc.lua
index 571ab7d..5df5e37 100644 (file)
@@ -5,48 +5,53 @@
 module("luci.controller.rpc", package.seeall)
 
 
-function index()
-       local function session_retrieve(sid, allowed_users)
-               local util = require "luci.util"
-               local sdat = util.ubus("session", "get", {
-                       ubus_rpc_session = sid
-               })
-
-               if type(sdat) == "table" and
-                  type(sdat.values) == "table" and
-                  type(sdat.values.token) == "string" and
-                  type(sdat.values.secret) == "string" and
-                  type(sdat.values.username) == "string" and
-                  util.contains(allowed_users, sdat.values.username)
-               then
-                       return sid, sdat.values
-               end
-
-               return nil
+function session_retrieve(sid, allowed_users)
+       local util = require "luci.util"
+       local sdat = util.ubus("session", "get", {
+               ubus_rpc_session = sid
+       })
+
+       if type(sdat) == "table" and
+          type(sdat.values) == "table" and
+          type(sdat.values.token) == "string" and
+          type(sdat.values.secret) == "string" and
+          type(sdat.values.username) == "string" and
+          util.contains(allowed_users, sdat.values.username)
+       then
+               return sid, sdat.values
        end
 
-       local function authenticator(validator, accs)
-               local http = require "luci.http"
-               local auth = http.formvalue("auth", true) or http.getcookie("sysauth")
+       return nil
+end
 
-               if auth then -- if authentication token was given
-                       local sid, sdat = session_retrieve(auth, accs)
-                       if sdat then -- if given token is valid
-                               return sdat.username, sid
-                       end
-                       http.status(403, "Forbidden")
+function authenticator(validator, accs)
+       local http = require "luci.http"
+       local ctrl = require "luci.controller.rpc"
+       local auth = http.formvalue("auth", true) or http.getcookie("sysauth")
+
+       if auth then -- if authentication token was given
+               local sid, sdat = ctrl.session_retrieve(auth, accs)
+               if sdat then -- if given token is valid
+                       return sdat.username, sid
                end
+               http.status(403, "Forbidden")
        end
+end
+
+
+function index()
+       local ctrl = require "luci.controller.rpc"
 
        local rpc = node("rpc")
        rpc.sysauth = "root"
-       rpc.sysauth_authenticator = authenticator
+       rpc.sysauth_authenticator = ctrl.authenticator
        rpc.notemplate = true
 
        entry({"rpc", "uci"}, call("rpc_uci"))
        entry({"rpc", "fs"}, call("rpc_fs"))
        entry({"rpc", "sys"}, call("rpc_sys"))
        entry({"rpc", "ipkg"}, call("rpc_ipkg"))
+       entry({"rpc", "ip"}, call("rpc_ip"))
        entry({"rpc", "auth"}, call("rpc_auth")).sysauth = false
 end
 
@@ -77,7 +82,7 @@ function rpc_auth()
                                }
                        })
 
-                       local sid, sdat = session_retrieve(login.ubus_rpc_session, { user })
+                       local sid, sdat = ctrl.session_retrieve(login.ubus_rpc_session, { user })
                        if sdat then
                                return {
                                        sid = sid,
@@ -160,13 +165,40 @@ function rpc_fs()
 end
 
 function rpc_sys()
+       local util    = require "luci.util"
        local sys     = require "luci.sys"
        local jsonrpc = require "luci.jsonrpc"
        local http    = require "luci.http"
        local ltn12   = require "luci.ltn12"
 
+       local sys2 = util.clone(sys)
+             sys2.net = util.clone(sys.net)
+             sys2.wifi = util.clone(sys.wifi)
+
+       function sys2.wifi.getiwinfo(ifname, operation)
+               local iw = sys.wifi.getiwinfo(ifname)
+               if iw then
+                       if operation then
+                               assert(type(iwinfo[iw.type][operation]) == "function")
+                               return iw[operation]
+                       end
+
+                       local n, f
+                       local rv = { ifname = ifname }
+                       for n, f in pairs(iwinfo[iw.type]) do
+                               if type(f) == "function" and
+                                  n ~= "scanlist" and n ~= "countrylist"
+                               then
+                                       rv[n] = iw[n]
+                               end
+                       end
+                       return rv
+               end
+               return nil
+       end
+
        http.prepare_content("application/json")
-       ltn12.pump.all(jsonrpc.handle(sys, http.source()), http.write)
+       ltn12.pump.all(jsonrpc.handle(sys2, http.source()), http.write)
 end
 
 function rpc_ipkg()
@@ -182,3 +214,34 @@ function rpc_ipkg()
        http.prepare_content("application/json")
        ltn12.pump.all(jsonrpc.handle(ipkg, http.source()), http.write)
 end
+
+function rpc_ip()
+       if not pcall(require, "luci.ip") then
+               luci.http.status(404, "Not Found")
+               return nil
+       end
+
+       local util    = require "luci.util"
+       local ip      = require "luci.ip"
+       local jsonrpc = require "luci.jsonrpc"
+       local http    = require "luci.http"
+       local ltn12   = require "luci.ltn12"
+
+       local ip2 = util.clone(ip)
+
+       local _, n
+       for _, n in ipairs({ "new", "IPv4", "IPv6", "MAC" }) do
+               ip2[n] = function(address, netmask, operation, argument)
+                       local cidr = ip[n](address, netmask)
+                       if cidr and operation then
+                               assert(type(cidr[operation]) == "function")
+                               local cidr2 = cidr[operation](cidr, argument)
+                               return (type(cidr2) == "userdata") and cidr2:string() or cidr2
+                       end
+                       return (type(cidr) == "userdata") and cidr:string() or cidr
+               end
+       end
+
+       http.prepare_content("application/json")
+       ltn12.pump.all(jsonrpc.handle(ip2, http.source()), http.write)
+end