luci-base: properly handle authentication without authenticator
authorJo-Philipp Wich <jo@mein.io>
Tue, 11 Jul 2017 12:12:50 +0000 (14:12 +0200)
committerJo-Philipp Wich <jo@mein.io>
Tue, 11 Jul 2017 12:12:50 +0000 (14:12 +0200)
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>
modules/luci-base/luasrc/dispatcher.lua

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