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,7 +183,8 @@ 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)
if util.contains(allowed_users, user) then
local login = util.ubus("session", "login", { local login = util.ubus("session", "login", {
username = user, username = user,
password = pass, password = pass,
@ -197,10 +199,11 @@ local function session_setup(user, pass)
values = { token = sys.uniqueid(16) } values = { token = sys.uniqueid(16) }
}) })
return login.ubus_rpc_session 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,10 +366,13 @@ 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 else
sid, sdat = session_retrieve(http.getcookie("sysauth"), allowed_users) sid = http.getcookie("sysauth")
end
if not sid then sid, sdat = session_retrieve(sid, allowed_users)
if not (sid and sdat) and authen == "htmlauth" then
local user = http.getenv("HTTP_AUTH_USER") local user = http.getenv("HTTP_AUTH_USER")
local pass = http.getenv("HTTP_AUTH_PASS") local pass = http.getenv("HTTP_AUTH_PASS")
@ -370,33 +381,25 @@ function dispatch(request)
pass = http.formvalue("luci_password") pass = http.formvalue("luci_password")
end end
if util.contains(allowed_users, user) then sid, sdat = session_setup(user, pass, allowed_users)
sid, sdat = session_setup(user, pass), nil
end
if not sid then if not sid then
require("luci.i18n") local tmpl = require "luci.template"
require("luci.template")
context.path = {} context.path = {}
http.status(403, "Forbidden") http.status(403, "Forbidden")
luci.template.render(track.sysauth_template or "sysauth", { tmpl.render(track.sysauth_template or "sysauth", {
duser = default_user, duser = default_user,
fuser = user fuser = user
}) })
return return
end end
http.header("Set-Cookie", 'sysauth=%s; path=%s' %{ sid, build_url() }) http.header("Set-Cookie", 'sysauth=%s; path=%s' %{ sid, build_url() })
http.redirect(build_url(unpack(ctx.requestpath))) http.redirect(build_url(unpack(ctx.requestpath)))
end end
else
error500("Unsupported authenticator configured")
return
end
if not sdat then
sid, sdat = session_retrieve(sid, allowed_users)
end
if not sid or not sdat then if not sid or not sdat then
http.status(403, "Forbidden") http.status(403, "Forbidden")