summaryrefslogtreecommitdiffhomepage
path: root/modules/luci-mod-rpc
diff options
context:
space:
mode:
authorJo-Philipp Wich <jo@mein.io>2018-04-06 07:56:56 +0200
committerJo-Philipp Wich <jo@mein.io>2018-04-06 07:56:56 +0200
commitfeefc600ed052207a9cef1f331abf2eedea35a66 (patch)
tree5938ea3d226a0254f0616a6b4e75dc1075d3f34d /modules/luci-mod-rpc
parentd6b4a3d45a37e4a6f4cfa8dcf275c8af3a8a198f (diff)
luci-mod-rpc: rework authentication and session handling
- Use the ubus session.login procedure to authenticate credentials - Fix testing of allowed usernames - Support authentication via sysauth cookie Fixes #1300, #1700, #1711 Signed-off-by: Jo-Philipp Wich <jo@mein.io>
Diffstat (limited to 'modules/luci-mod-rpc')
-rw-r--r--modules/luci-mod-rpc/luasrc/controller/rpc.lua95
1 files changed, 63 insertions, 32 deletions
diff --git a/modules/luci-mod-rpc/luasrc/controller/rpc.lua b/modules/luci-mod-rpc/luasrc/controller/rpc.lua
index 759bb749cf..3326d57a95 100644
--- a/modules/luci-mod-rpc/luasrc/controller/rpc.lua
+++ b/modules/luci-mod-rpc/luasrc/controller/rpc.lua
@@ -7,23 +7,45 @@ local pairs = pairs
local print = print
local pcall = pcall
local table = table
+local type = type
+local tonumber = tonumber
module "luci.controller.rpc"
-function index()
- local function authenticator(validator, accs)
- local auth = luci.http.formvalue("auth", true)
- if auth then -- if authentication token was given
- local sdat = (luci.util.ubus("session", "get", { ubus_rpc_session = auth }) or { }).values
- if sdat then -- if given token is valid
- if sdat.user and luci.util.contains(accs, sdat.user) then
- return sdat.user, auth
- end
- end
+
+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
+end
+
+local function authenticator(validator, accs)
+ local auth = luci.http.formvalue("auth", true)
+ or luci.http.getcookie("sysauth")
+
+ 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
luci.http.status(403, "Forbidden")
end
+end
+function index()
local rpc = node("rpc")
rpc.sysauth = "root"
rpc.sysauth_authenticator = authenticator
@@ -43,39 +65,48 @@ function rpc_auth()
local ltn12 = require "luci.ltn12"
local util = require "luci.util"
- local loginstat
-
local server = {}
server.challenge = function(user, pass)
- local sid, token, secret
-
local config = require "luci.config"
-
- if sys.user.checkpasswd(user, pass) then
- local sdat = util.ubus("session", "create", { timeout = config.sauth.sessiontime })
+ local login = util.ubus("session", "login", {
+ username = user,
+ password = pass,
+ timeout = tonumber(config.sauth.sessiontime)
+ })
+
+ if type(login) == "table" and
+ type(login.ubus_rpc_session) == "string"
+ then
+ util.ubus("session", "set", {
+ ubus_rpc_session = login.ubus_rpc_session,
+ values = {
+ token = sys.uniqueid(16),
+ secret = sys.uniqueid(16)
+ }
+ })
+
+ local sid, sdat = session_retrieve(login.ubus_rpc_session, { user })
if sdat then
- sid = sdat.ubus_rpc_session
- token = sys.uniqueid(16)
- secret = sys.uniqueid(16)
-
- http.header("Set-Cookie", "sysauth="..sid.."; path=/")
- util.ubus("session", "set", {
- ubus_rpc_session = sid,
- values = {
- user = user,
- token = token,
- secret = secret
- }
- })
+ return {
+ sid = sid,
+ token = sdat.token,
+ secret = sdat.secret
+ }
end
end
- return sid and {sid=sid, token=token, secret=secret}
+ return nil
end
server.login = function(...)
local challenge = server.challenge(...)
- return challenge and challenge.sid
+ if challenge then
+ http.header("Set-Cookie", 'sysauth=%s; path=%s' %{
+ challenge.sid,
+ http.getenv("SCRIPT_NAME")
+ })
+ return challenge.sid
+ end
end
http.prepare_content("application/json")