From b868ff91566270c2bebe350b1d671f467bf08601 Mon Sep 17 00:00:00 2001 From: Bryce Kwon Date: Mon, 2 Nov 2026 19:52:14 -1000 Subject: Say that logging in needs https Only HTTPS=on counts, the same test cgit makes before it writes an https link of its own. --- custom/extensions/auth-file.lua | 11 +++++++++-- custom/extensions/auth-inline.lua | 11 +++++++++-- tests/extensions/test-auth.lua | 13 ++++++++++++- 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/custom/extensions/auth-file.lua b/custom/extensions/auth-file.lua index f05a59e..790c1fd 100644 --- a/custom/extensions/auth-file.lua +++ b/custom/extensions/auth-file.lua @@ -18,7 +18,9 @@ -- -- The session cookie is marked Secure by default, so a browser only sends -- it back over HTTPS. On an instance served over plain HTTP login loops --- until cookie_insecure below is set. +-- until cookie_insecure below is set. The login form warns of this whenever +-- the web server does not pass HTTPS=on, so one behind a proxy that ends TLS +-- should set that by hand. -- -- Two libraries are needed. luaossl provides openssl.rand and openssl.hmac and -- lives at , and luaposix provides @@ -533,6 +535,11 @@ function body() html("") return 0 end + -- The session cookie is Secure, so over plain http the browser never + -- sends it back and a login would only bring the form round again. + if not cookie_insecure and http["https"] ~= "on" then + html("") + end -- cgit asks for the form only once the cookie has been turned down, so -- a session that still verifies belongs to someone not let in here. local cookie = get_cookie(http["cookie"], session_cookie) @@ -571,7 +578,7 @@ function filter_open(name, cookie, method, query, referer, path, host, https, repo, page, url, login) action = actions[name] post = {} - http = { cookie = cookie } + http = { cookie = cookie, https = https } cgit = { repo = repo, url = url, login = login } end diff --git a/custom/extensions/auth-inline.lua b/custom/extensions/auth-inline.lua index 878d55e..99e33d2 100644 --- a/custom/extensions/auth-inline.lua +++ b/custom/extensions/auth-inline.lua @@ -20,7 +20,9 @@ -- -- The session cookie is marked Secure by default, so a browser only sends -- it back over HTTPS. On an instance served over plain HTTP login loops --- until cookie_insecure below is set. +-- until cookie_insecure below is set. The login form warns of this whenever +-- the web server does not pass HTTPS=on, so one behind a proxy that ends TLS +-- should set that by hand. -- -- Two libraries are needed. luaossl provides openssl.rand and openssl.hmac and -- lives at , and luaposix provides @@ -496,6 +498,11 @@ function body() html("") return 0 end + -- The session cookie is Secure, so over plain http the browser never + -- sends it back and a login would only bring the form round again. + if not cookie_insecure and http["https"] ~= "on" then + html("") + end -- cgit asks for the form only once the cookie has been turned down, so -- a session that still verifies belongs to someone not let in here. local cookie = get_cookie(http["cookie"], session_cookie) @@ -534,7 +541,7 @@ function filter_open(name, cookie, method, query, referer, path, host, https, repo, page, url, login) action = actions[name] post = {} - http = { cookie = cookie } + http = { cookie = cookie, https = https } cgit = { repo = repo, url = url, login = login } end diff --git a/tests/extensions/test-auth.lua b/tests/extensions/test-auth.lua index db97bb3..73843ab 100644 --- a/tests/extensions/test-auth.lua +++ b/tests/extensions/test-auth.lua @@ -228,7 +228,7 @@ local function run_action(action, opts) opts = opts or {} h.reset() filter_open(action, opts.cookie or "", opts.method or "GET", "", "", - "/", "example.org", "on", opts.repo or "", "summary", + "/", "example.org", opts.https or "on", opts.repo or "", "summary", opts.url or "/repo/", "/?p=login") if opts.body then filter_write(opts.body) @@ -300,6 +300,15 @@ h.check("and can still sign in as someone else", way_back_in(out) ~= nil) out = run_action("body", { cookie = session_name .. "=" .. forged }) h.excludes("a forged session is not taken for a signed-in visitor", out, "signed in") +-- The session cookie is Secure, so a form served over plain http would only +-- come round again after every login. +out = run_action("body", { https = "" }) +h.contains("over plain http the form says logging in needs https", out, + "") +h.check("and is still there to fill in", way_back_in(out) ~= nil) +out = run_action("body", {}) +h.excludes("over https it says nothing of the kind", out, "only works over https") + out = run_action("body", { url = "//evil.example/x" }) h.equals("an unsafe destination is swapped for the login page", way_back_in(out), "/?p=login") h.equals("and is not taken for a failed login", out:find("login-error", 1, true), nil) @@ -370,6 +379,8 @@ load_script({ { "local cookie_insecure = false", "local cookie_insecure = true" out = login("Alice", password, way_back) h.contains("an insecure session cookie keeps its plain name", out, "Set-Cookie: cgitauth=") h.excludes("and is not marked Secure", out, "; Secure") +out = run_action("body", { https = "" }) +h.excludes("so its form does not ask for https", out, "only works over https") load_script() -- A cookie carries whole seconds, while on Lua 5.3 and later a session length -- cgit 2.12.1