luci-base: switch to ubus sessions
authorJo-Philipp Wich <jow@openwrt.org>
Thu, 15 Jan 2015 09:55:53 +0000 (10:55 +0100)
committerJo-Philipp Wich <jow@openwrt.org>
Thu, 15 Jan 2015 10:09:05 +0000 (11:09 +0100)
Remove luci.sauth session storage implementation and offload the session
management to the rpcd ubus backend. Also depend on rpcd due to this.

modules/luci-base/Makefile
modules/luci-base/luasrc/dispatcher.lua
modules/luci-base/luasrc/sauth.lua [deleted file]
modules/luci-mod-admin-full/luasrc/controller/admin/index.lua
modules/luci-mod-admin-mini/luasrc/controller/mini/index.lua
modules/luci-mod-rpc/luasrc/controller/rpc.lua

index 15aababbb784f7447625a4b019fe08577405af53..8337fea71138c0c11d8b279efb811a4c6f5bbb94 100644 (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
index f7e16e77b69d403e4ab3e5466e7ea199e83b5ab7..4bbd58f9dbb32729ef5ae8ac42b44bce5183394a 100644 (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")
diff --git a/modules/luci-base/luasrc/sauth.lua b/modules/luci-base/luasrc/sauth.lua
deleted file mode 100644 (file)
index 32f172d..0000000
+++ /dev/null
@@ -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
index 4e832529d9128bfd64430669b95cd6dd976d1c0d..64a620ca284db9d00fa96dc8360889b4c69ce058 100644 (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
 
index 9d6a38ed4373cbc3711f145d42907c9f3e8b621f..6800f9bfd9f186c69670031b2eef778d59e4b7bf 100644 (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
 
index 359184c744c11e1e6eb992fcb6acd5cc3b135c36..92947168e447847e02a6b25439edd2c6578046db 100644 (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)
-
-                       http.header("Set-Cookie", "sysauth=" .. sid.."; path=/")
-                       sauth.reap()
-                       sauth.write(sid, {
-                               user=user,
-                               token=token,
-                               secret=secret
-                       })
+                       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=/")
+                               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}