luci-base: switch to ubus sessions
Remove luci.sauth session storage implementation and offload the session management to the rpcd ubus backend. Also depend on rpcd due to this.
This commit is contained in:
parent
eb8560061a
commit
199c8cbc4c
6 changed files with 46 additions and 159 deletions
|
@ -12,7 +12,7 @@ LUCI_TYPE:=mod
|
|||
LUCI_BASENAME:=base
|
||||
|
||||
LUCI_TITLE:=LuCI core libraries
|
||||
LUCI_DEPENDS:=+lua +libuci-lua +luci-lib-nixio
|
||||
LUCI_DEPENDS:=+lua +libuci-lua +luci-lib-nixio +rpcd
|
||||
|
||||
PKG_SOURCE:=LuaSrcDiet-0.12.1.tar.bz2
|
||||
PKG_SOURCE_URL:=https://luasrcdiet.googlecode.com/files
|
||||
|
|
|
@ -333,8 +333,6 @@ function dispatch(request)
|
|||
)
|
||||
|
||||
if track.sysauth then
|
||||
local sauth = require "luci.sauth"
|
||||
|
||||
local authen = type(track.sysauth_authenticator) == "function"
|
||||
and track.sysauth_authenticator
|
||||
or authenticator[track.sysauth_authenticator]
|
||||
|
@ -349,7 +347,7 @@ function dispatch(request)
|
|||
verifytoken = true
|
||||
end
|
||||
|
||||
local sdat = sauth.read(sess)
|
||||
local sdat = (util.ubus("session", "get", { ubus_rpc_session = sess }) or { }).values
|
||||
local user
|
||||
|
||||
if sdat then
|
||||
|
@ -371,20 +369,28 @@ function dispatch(request)
|
|||
if not user or not util.contains(accs, user) then
|
||||
return
|
||||
else
|
||||
local sid = sess or luci.sys.uniqueid(16)
|
||||
if not sess then
|
||||
local token = luci.sys.uniqueid(16)
|
||||
sauth.reap()
|
||||
sauth.write(sid, {
|
||||
user=user,
|
||||
token=token,
|
||||
secret=luci.sys.uniqueid(16)
|
||||
})
|
||||
ctx.urltoken.stok = token
|
||||
local sdat = util.ubus("session", "create", { timeout = luci.config.sauth.sessiontime })
|
||||
if sdat then
|
||||
local token = luci.sys.uniqueid(16)
|
||||
util.ubus("session", "set", {
|
||||
ubus_rpc_session = sdat.ubus_rpc_session,
|
||||
values = {
|
||||
user = user,
|
||||
token = token,
|
||||
section = luci.sys.uniqueid(16)
|
||||
}
|
||||
})
|
||||
sess = sdat.ubus_rpc_session
|
||||
ctx.urltoken.stok = token
|
||||
end
|
||||
end
|
||||
|
||||
if sess then
|
||||
luci.http.header("Set-Cookie", "sysauth=" .. sess.."; path="..build_url())
|
||||
ctx.authsession = sess
|
||||
ctx.authuser = user
|
||||
end
|
||||
luci.http.header("Set-Cookie", "sysauth=" .. sid.."; path="..build_url())
|
||||
ctx.authsession = sid
|
||||
ctx.authuser = user
|
||||
end
|
||||
else
|
||||
luci.http.status(403, "Forbidden")
|
||||
|
|
|
@ -1,127 +0,0 @@
|
|||
--[[
|
||||
|
||||
Session authentication
|
||||
(c) 2008 Steven Barth <steven@midlink.org>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
$Id$
|
||||
|
||||
]]--
|
||||
|
||||
--- LuCI session library.
|
||||
module("luci.sauth", package.seeall)
|
||||
require("luci.util")
|
||||
require("luci.sys")
|
||||
require("luci.config")
|
||||
local nixio = require "nixio", require "nixio.util"
|
||||
local fs = require "nixio.fs"
|
||||
|
||||
|
||||
luci.config.sauth = luci.config.sauth or {}
|
||||
sessionpath = luci.config.sauth.sessionpath
|
||||
sessiontime = tonumber(luci.config.sauth.sessiontime) or 15 * 60
|
||||
|
||||
--- Prepare session storage by creating the session directory.
|
||||
function prepare()
|
||||
fs.mkdir(sessionpath, 700)
|
||||
if not sane() then
|
||||
error("Security Exception: Session path is not sane!")
|
||||
end
|
||||
end
|
||||
|
||||
local function _read(id)
|
||||
local blob = fs.readfile(sessionpath .. "/" .. id)
|
||||
return blob
|
||||
end
|
||||
|
||||
local function _write(id, data)
|
||||
local f = nixio.open(sessionpath .. "/" .. id, "w", 600)
|
||||
f:writeall(data)
|
||||
f:close()
|
||||
end
|
||||
|
||||
local function _checkid(id)
|
||||
return not not (id and #id == 32 and id:match("^[a-fA-F0-9]+$"))
|
||||
end
|
||||
|
||||
--- Write session data to a session file.
|
||||
-- @param id Session identifier
|
||||
-- @param data Session data table
|
||||
function write(id, data)
|
||||
if not sane() then
|
||||
prepare()
|
||||
end
|
||||
|
||||
assert(_checkid(id), "Security Exception: Session ID is invalid!")
|
||||
assert(type(data) == "table", "Security Exception: Session data invalid!")
|
||||
|
||||
data.atime = luci.sys.uptime()
|
||||
|
||||
_write(id, luci.util.get_bytecode(data))
|
||||
end
|
||||
|
||||
--- Read a session and return its content.
|
||||
-- @param id Session identifier
|
||||
-- @return Session data table or nil if the given id is not found
|
||||
function read(id)
|
||||
if not id or #id == 0 then
|
||||
return nil
|
||||
end
|
||||
|
||||
assert(_checkid(id), "Security Exception: Session ID is invalid!")
|
||||
|
||||
if not sane(sessionpath .. "/" .. id) then
|
||||
return nil
|
||||
end
|
||||
|
||||
local blob = _read(id)
|
||||
local func = loadstring(blob)
|
||||
setfenv(func, {})
|
||||
|
||||
local sess = func()
|
||||
assert(type(sess) == "table", "Session data invalid!")
|
||||
|
||||
if sess.atime and sess.atime + sessiontime < luci.sys.uptime() then
|
||||
kill(id)
|
||||
return nil
|
||||
end
|
||||
|
||||
-- refresh atime in session
|
||||
write(id, sess)
|
||||
|
||||
return sess
|
||||
end
|
||||
|
||||
--- Check whether Session environment is sane.
|
||||
-- @return Boolean status
|
||||
function sane(file)
|
||||
return luci.sys.process.info("uid")
|
||||
== fs.stat(file or sessionpath, "uid")
|
||||
and fs.stat(file or sessionpath, "modestr")
|
||||
== (file and "rw-------" or "rwx------")
|
||||
end
|
||||
|
||||
--- Kills a session
|
||||
-- @param id Session identifier
|
||||
function kill(id)
|
||||
assert(_checkid(id), "Security Exception: Session ID is invalid!")
|
||||
fs.unlink(sessionpath .. "/" .. id)
|
||||
end
|
||||
|
||||
--- Remove all expired session data files
|
||||
function reap()
|
||||
if sane() then
|
||||
local id
|
||||
for id in nixio.fs.dir(sessionpath) do
|
||||
if _checkid(id) then
|
||||
-- reading the session will kill it if it is expired
|
||||
read(id)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -38,9 +38,11 @@ end
|
|||
|
||||
function action_logout()
|
||||
local dsp = require "luci.dispatcher"
|
||||
local sauth = require "luci.sauth"
|
||||
local utl = require "luci.util"
|
||||
if dsp.context.authsession then
|
||||
sauth.kill(dsp.context.authsession)
|
||||
utl.ubus("session", "destroy", {
|
||||
ubus_rpc_session = dsp.context.authsession
|
||||
})
|
||||
dsp.context.urltoken.stok = nil
|
||||
end
|
||||
|
||||
|
|
|
@ -37,9 +37,11 @@ end
|
|||
|
||||
function action_logout()
|
||||
local dsp = require "luci.dispatcher"
|
||||
local sauth = require "luci.sauth"
|
||||
local utl = require "luci.util"
|
||||
if dsp.context.authsession then
|
||||
sauth.kill(dsp.context.authsession)
|
||||
utl.ubus("session", "destroy", {
|
||||
ubus_rpc_session = dsp.context.authsession
|
||||
})
|
||||
dsp.context.urltoken.stok = nil
|
||||
end
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ 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.sauth.read(auth)
|
||||
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
|
||||
|
@ -49,7 +49,6 @@ end
|
|||
|
||||
function rpc_auth()
|
||||
local jsonrpc = require "luci.jsonrpc"
|
||||
local sauth = require "luci.sauth"
|
||||
local http = require "luci.http"
|
||||
local sys = require "luci.sys"
|
||||
local ltn12 = require "luci.ltn12"
|
||||
|
@ -62,17 +61,22 @@ function rpc_auth()
|
|||
local sid, token, secret
|
||||
|
||||
if sys.user.checkpasswd(user, pass) then
|
||||
sid = sys.uniqueid(16)
|
||||
token = sys.uniqueid(16)
|
||||
secret = sys.uniqueid(16)
|
||||
local sdat = util.ubus("session", "create", { timeout = luci.config.sauth.sessiontime })
|
||||
if sdat then
|
||||
sid = sdat.ubus_rpc_session
|
||||
token = sys.uniqueid(16)
|
||||
secret = sys.uniqueid(16)
|
||||
|
||||
http.header("Set-Cookie", "sysauth=" .. sid.."; path=/")
|
||||
sauth.reap()
|
||||
sauth.write(sid, {
|
||||
user=user,
|
||||
token=token,
|
||||
secret=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
|
||||
|
||||
return sid and {sid=sid, token=token, secret=secret}
|
||||
|
|
Loading…
Reference in a new issue