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:
Jo-Philipp Wich 2015-01-15 10:55:53 +01:00
parent eb8560061a
commit 199c8cbc4c
6 changed files with 46 additions and 159 deletions

View file

@ -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

View file

@ -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")

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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}