diff mbox series

LuCI: implement TLS client certificate authentication

Message ID 20210219200152.1346055-1-luka.logar@cifra.si
State New
Headers show
Series LuCI: implement TLS client certificate authentication | expand

Commit Message

Luka Logar Feb. 19, 2021, 8:01 p.m. UTC
When available, pass TLS client certificate data (subject name & cert hash) to the rpcd daemon
for authentication (as username and password). Add an extra mode='cert' parameter, so the rpcd
is aware they come from certificate and are treated accordingly

Signed-off-by: Luka Logar <luka.logar@cifra.si>
---
 .../luasrc/controller/admin/index.lua         |  3 +++
 modules/luci-base/luasrc/dispatcher.lua       | 24 +++++++++++++++++--
 modules/luci-base/luasrc/view/error401.htm    |  6 +++++
 modules/luci-base/luasrc/view/logout.htm      |  6 +++++
 4 files changed, 37 insertions(+), 2 deletions(-)
 create mode 100644 modules/luci-base/luasrc/view/error401.htm
 create mode 100644 modules/luci-base/luasrc/view/logout.htm
diff mbox series

Patch

diff --git a/modules/luci-base/luasrc/controller/admin/index.lua b/modules/luci-base/luasrc/controller/admin/index.lua
index 736d0cdcc..5167ea952 100644
--- a/modules/luci-base/luasrc/controller/admin/index.lua
+++ b/modules/luci-base/luasrc/controller/admin/index.lua
@@ -14,6 +14,9 @@  function action_logout()
 		luci.http.header("Set-Cookie", "sysauth=%s; expires=%s; path=%s" %{
 			'', 'Thu, 01 Jan 1970 01:00:00 GMT', dsp.build_url()
 		})
+
+		luci.template.render("logout")
+		return
 	end
 
 	luci.http.redirect(dsp.build_url())
diff --git a/modules/luci-base/luasrc/dispatcher.lua b/modules/luci-base/luasrc/dispatcher.lua
index 44c17c85f..f0229dba9 100644
--- a/modules/luci-base/luasrc/dispatcher.lua
+++ b/modules/luci-base/luasrc/dispatcher.lua
@@ -546,11 +546,12 @@  local function session_retrieve(sid, allowed_users)
 	return nil, nil, nil
 end
 
-local function session_setup(user, pass)
+local function session_setup(user, pass, mode)
 	local login = util.ubus("session", "login", {
 		username = user,
 		password = pass,
-		timeout  = tonumber(luci.config.sauth.sessiontime)
+		timeout  = tonumber(luci.config.sauth.sessiontime),
+		mode = mode
 	})
 
 	local rp = context.requestpath
@@ -866,6 +867,25 @@  function dispatch(request)
 			end
 		end
 
+		if not (sid and sdat and sacl) and auth.login then
+			local user = http.getenv("HTTPS_CLIENT_CERT_SN")
+			local pass = http.getenv("HTTPS_CLIENT_CERT_SHA256")
+
+			if user and pass then
+				sid, sdat, sacl = session_setup(user, pass, "cert")
+
+				if not sid then
+					http.status(401, "Unauthorized")
+					tpl.render("error401")
+					return
+				end
+
+				http.header("Set-Cookie", 'sysauth=%s; path=%s; SameSite=Strict; HttpOnly; secure' %{
+					sid, build_url()
+				})
+			end
+		end
+
 		if not (sid and sdat and sacl) and auth.login then
 			local user = http.getenv("HTTP_AUTH_USER")
 			local pass = http.getenv("HTTP_AUTH_PASS")
diff --git a/modules/luci-base/luasrc/view/error401.htm b/modules/luci-base/luasrc/view/error401.htm
new file mode 100644
index 000000000..e6e18e5ad
--- /dev/null
+++ b/modules/luci-base/luasrc/view/error401.htm
@@ -0,0 +1,6 @@ 
+<%#
+ Copyright 2021 Luka Logar <luka.logar@iname.com>
+ Licensed to the public under the Apache License 2.0.
+-%>
+
+<h2 name="content">401 <%:Unauthorized%></h2>
diff --git a/modules/luci-base/luasrc/view/logout.htm b/modules/luci-base/luasrc/view/logout.htm
new file mode 100644
index 000000000..fb38ed51d
--- /dev/null
+++ b/modules/luci-base/luasrc/view/logout.htm
@@ -0,0 +1,6 @@ 
+<%#
+ Copyright 2021 Luka Logar <luka.logar@iname.com>
+ Licensed to the public under the Apache License 2.0.
+-%>
+
+<h2 name="content"><%:User logged out, please close the browser window%></h2>