luci-base: properly handle authentication without authenticator

Some controller actions like the ones in "servicectl" require authentication
but are not meant to provide an authenticator because they're only invoked
by scripts.

Rework the dispatcher logic to handle this situation and only bail out if
an authenticator name other than "htmlauth" is set.

Signed-off-by: Jo-Philipp Wich <jo@mein.io>
This commit is contained in:
Jo-Philipp Wich 2017-07-11 14:12:50 +02:00
parent 882427731a
commit 4e1b884157

View file

@ -174,7 +174,8 @@ local function session_retrieve(sid, allowed_users)
if type(sdat) == "table" and if type(sdat) == "table" and
type(sdat.values) == "table" and type(sdat.values) == "table" and
type(sdat.values.token) == "string" and type(sdat.values.token) == "string" and
util.contains(allowed_users, sdat.values.username) (not allowed_users or
util.contains(allowed_users, sdat.values.username))
then then
return sid, sdat.values return sid, sdat.values
end end
@ -182,25 +183,27 @@ local function session_retrieve(sid, allowed_users)
return nil, nil return nil, nil
end end
local function session_setup(user, pass) local function session_setup(user, pass, allowed_users)
local login = util.ubus("session", "login", { if util.contains(allowed_users, user) then
username = user, local login = util.ubus("session", "login", {
password = pass, username = user,
timeout = tonumber(luci.config.sauth.sessiontime) password = pass,
}) timeout = tonumber(luci.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) }
}) })
return login.ubus_rpc_session 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) }
})
return session_retrieve(login.ubus_rpc_session)
end
end end
return nil return nil, nil
end end
function dispatch(request) function dispatch(request)
@ -350,6 +353,11 @@ function dispatch(request)
local authen = track.sysauth_authenticator local authen = track.sysauth_authenticator
local _, sid, sdat, default_user, allowed_users local _, sid, sdat, default_user, allowed_users
if type(authen) == "string" and authen ~= "htmlauth" then
error500("Unsupported authenticator %q configured" % authen)
return
end
if type(track.sysauth) == "table" then if type(track.sysauth) == "table" then
default_user, allowed_users = nil, track.sysauth default_user, allowed_users = nil, track.sysauth
else else
@ -358,44 +366,39 @@ function dispatch(request)
if type(authen) == "function" then if type(authen) == "function" then
_, sid = authen(sys.user.checkpasswd, allowed_users) _, sid = authen(sys.user.checkpasswd, allowed_users)
elseif authen == "htmlauth" then
sid, sdat = session_retrieve(http.getcookie("sysauth"), allowed_users)
if not sid then
local user = http.getenv("HTTP_AUTH_USER")
local pass = http.getenv("HTTP_AUTH_PASS")
if user == nil and pass == nil then
user = http.formvalue("luci_username")
pass = http.formvalue("luci_password")
end
if util.contains(allowed_users, user) then
sid, sdat = session_setup(user, pass), nil
end
if not sid then
require("luci.i18n")
require("luci.template")
context.path = {}
http.status(403, "Forbidden")
luci.template.render(track.sysauth_template or "sysauth", {
duser = default_user,
fuser = user
})
return
end
http.header("Set-Cookie", 'sysauth=%s; path=%s' %{ sid, build_url() })
http.redirect(build_url(unpack(ctx.requestpath)))
end
else else
error500("Unsupported authenticator configured") sid = http.getcookie("sysauth")
return
end end
if not sdat then sid, sdat = session_retrieve(sid, allowed_users)
sid, sdat = session_retrieve(sid, allowed_users)
if not (sid and sdat) and authen == "htmlauth" then
local user = http.getenv("HTTP_AUTH_USER")
local pass = http.getenv("HTTP_AUTH_PASS")
if user == nil and pass == nil then
user = http.formvalue("luci_username")
pass = http.formvalue("luci_password")
end
sid, sdat = session_setup(user, pass, allowed_users)
if not sid then
local tmpl = require "luci.template"
context.path = {}
http.status(403, "Forbidden")
tmpl.render(track.sysauth_template or "sysauth", {
duser = default_user,
fuser = user
})
return
end
http.header("Set-Cookie", 'sysauth=%s; path=%s' %{ sid, build_url() })
http.redirect(build_url(unpack(ctx.requestpath)))
end end
if not sid or not sdat then if not sid or not sdat then