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>
This commit is contained in:
parent
d6b4a3d45a
commit
feefc600ed
1 changed files with 62 additions and 31 deletions
|
@ -7,23 +7,45 @@ local pairs = pairs
|
||||||
local print = print
|
local print = print
|
||||||
local pcall = pcall
|
local pcall = pcall
|
||||||
local table = table
|
local table = table
|
||||||
|
local type = type
|
||||||
|
local tonumber = tonumber
|
||||||
|
|
||||||
module "luci.controller.rpc"
|
module "luci.controller.rpc"
|
||||||
|
|
||||||
function index()
|
|
||||||
local function authenticator(validator, accs)
|
local function session_retrieve(sid, allowed_users)
|
||||||
local auth = luci.http.formvalue("auth", true)
|
local util = require "luci.util"
|
||||||
if auth then -- if authentication token was given
|
local sdat = util.ubus("session", "get", {
|
||||||
local sdat = (luci.util.ubus("session", "get", { ubus_rpc_session = auth }) or { }).values
|
ubus_rpc_session = sid
|
||||||
if sdat then -- if given token is valid
|
})
|
||||||
if sdat.user and luci.util.contains(accs, sdat.user) then
|
|
||||||
return sdat.user, auth
|
if type(sdat) == "table" and
|
||||||
end
|
type(sdat.values) == "table" and
|
||||||
end
|
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
|
end
|
||||||
luci.http.status(403, "Forbidden")
|
luci.http.status(403, "Forbidden")
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function index()
|
||||||
local rpc = node("rpc")
|
local rpc = node("rpc")
|
||||||
rpc.sysauth = "root"
|
rpc.sysauth = "root"
|
||||||
rpc.sysauth_authenticator = authenticator
|
rpc.sysauth_authenticator = authenticator
|
||||||
|
@ -43,39 +65,48 @@ function rpc_auth()
|
||||||
local ltn12 = require "luci.ltn12"
|
local ltn12 = require "luci.ltn12"
|
||||||
local util = require "luci.util"
|
local util = require "luci.util"
|
||||||
|
|
||||||
local loginstat
|
|
||||||
|
|
||||||
local server = {}
|
local server = {}
|
||||||
server.challenge = function(user, pass)
|
server.challenge = function(user, pass)
|
||||||
local sid, token, secret
|
|
||||||
|
|
||||||
local config = require "luci.config"
|
local config = require "luci.config"
|
||||||
|
local login = util.ubus("session", "login", {
|
||||||
|
username = user,
|
||||||
|
password = pass,
|
||||||
|
timeout = tonumber(config.sauth.sessiontime)
|
||||||
|
})
|
||||||
|
|
||||||
if sys.user.checkpasswd(user, pass) then
|
if type(login) == "table" and
|
||||||
local sdat = util.ubus("session", "create", { timeout = config.sauth.sessiontime })
|
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
|
if sdat then
|
||||||
sid = sdat.ubus_rpc_session
|
return {
|
||||||
token = sys.uniqueid(16)
|
sid = sid,
|
||||||
secret = sys.uniqueid(16)
|
token = sdat.token,
|
||||||
|
secret = sdat.secret
|
||||||
http.header("Set-Cookie", "sysauth="..sid.."; path=/")
|
}
|
||||||
util.ubus("session", "set", {
|
|
||||||
ubus_rpc_session = sid,
|
|
||||||
values = {
|
|
||||||
user = user,
|
|
||||||
token = token,
|
|
||||||
secret = secret
|
|
||||||
}
|
|
||||||
})
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return sid and {sid=sid, token=token, secret=secret}
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
server.login = function(...)
|
server.login = function(...)
|
||||||
local challenge = server.challenge(...)
|
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
|
end
|
||||||
|
|
||||||
http.prepare_content("application/json")
|
http.prepare_content("application/json")
|
||||||
|
|
Loading…
Reference in a new issue