diff options
context:
space:
mode:
authorBryce Kwon <bryce@brycekwon.com>
committerBryce Kwon <bryce@brycekwon.com>
commit
parent
tree
download
Trim the comments and dead code across the tree
Diffstat (limited to 'custom/extensions/auth-file.lua')
-rw-r--r--custom/extensions/auth-file.lua73
1 file changed, 29 insertions, 44 deletions
diff --git a/custom/extensions/auth-file.lua b/custom/extensions/auth-file.lua
index 74a04b6..957bd49 100644
--- a/custom/extensions/auth-file.lua
+++ b/custom/extensions/auth-file.lua
@@ -11,11 +11,9 @@
-- be the same Lua that cgit was built against. Lua 5.5 will not do, because
-- luaossl has no 5.5 build.
--
--- Serve cgit over HTTPS and terminate TLS in the web server in front of it.
--- The session cookie is marked Secure by default, so a browser only sends it
--- back over HTTPS, and on an instance served over plain HTTP with no TLS
--- anywhere the cookie never comes back and login appears to loop until
--- cookie_insecure below is set.
+-- 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.
--
-- Two libraries are needed. luaossl provides openssl.rand and openssl.hmac and
-- lives at <https://github.com/wahern/luaossl>, and luaposix provides
@@ -42,16 +40,10 @@
-- luarocks install luaossl OPENSSL_DIR="$(brew --prefix openssl)"
-- luarocks install luaposix
--
--- Some distributions package both as well, for example lua-luaossl and
--- lua-posix on Debian, and such a package has to be built for the same Lua
--- version as cgit.
---
--- The cookie carries only a user name and there is no server-side session
--- store, so deleting an account does not revoke a cookie already issued until
--- it expires, and instances that share a secret file accept each other's
--- cookies. The login form carries no CSRF token. Both are acceptable for
--- gating read access to a git browser, so weigh them before guarding anything
--- more sensitive.
+-- There is no server-side session store and no CSRF token, so a deleted
+-- account's cookie stays valid until it expires and instances sharing a
+-- secret file accept each other's cookies. That is acceptable for gating
+-- read access to a git browser, so weigh it before guarding anything more.
local sysstat = require("posix.sys.stat")
local unistd = require("posix.unistd")
@@ -59,7 +51,6 @@ local rand = require("openssl.rand")
local hmac = require("openssl.hmac")
-- The values that follow are the configuration and are meant to be edited.
--- Nothing below them needs changing for ordinary use.
-- Accounts live one per line as username:hash. Generate a hash with
-- mkpasswd -m sha-512 -R 300000
@@ -73,7 +64,7 @@ local groups_filename = "/etc/cgit-auth/groups"
-- Per-repository access lives one per line as reponame:group1,group2 and so
-- on. A repository named here is protected and one that is not named is
-- public. The repository name has to match exactly, while group and user names
--- match whatever their case.
+-- match regardless of case.
local repos_filename = "/etc/cgit-auth/repos"
-- Where the cookie-signing secret is stored, created on first use. It must be
@@ -91,8 +82,7 @@ local cookie_name = "cgitauth"
-- more tightly.
local cookie_path = "/"
--- Leave this false so the cookie is marked Secure and only travels over HTTPS.
--- Set it true only if cgit is served over plain HTTP with no TLS anywhere.
+-- Set this true only if cgit is served over plain HTTP with no TLS anywhere.
local cookie_insecure = false
-- A throwaway hash of the documented shape, used only to spend the same work
@@ -104,9 +94,8 @@ local dummy_hash = "$6$rounds=300000$0000000000000000$"
-- open decodes is kept here for the calls that follow.
local action, http, cgit, post
--- The two lookups below, account_hash and repo_userset, are the only part of
--- this script that differs from auth-inline.lua. Replacing them is all it
--- takes to keep accounts somewhere else.
+-- The two lookups below, account_hash and repo_userset, are the only part
+-- of this script that differs from auth-inline.lua.
local function trim(s)
return (string.gsub(s, "^%s*(.-)%s*$", "%1"))
@@ -118,14 +107,12 @@ local function add_names(list, set)
end
end
--- A missing or unreadable users file is not fatal, and neither is a line that
--- does not parse, so a broken file turns every login down rather than failing
--- the request outright.
+-- A missing, unreadable or unparsable users file turns every login down
+-- rather than failing the request outright.
--
--- The hash is trimmed as well as the name because reading by line strips the
--- newline but not a carriage return, so a users file saved with CRLF endings
--- would otherwise hand crypt a hash with a trailing \r and fail every login
--- with nothing in the log to say why.
+-- The hash is trimmed as well as the name because reading by line strips
+-- the newline but not a carriage return, so a CRLF users file would hand
+-- crypt a hash with a trailing \r and fail every login.
function account_hash(user)
if user == nil then
return nil
@@ -224,14 +211,9 @@ local function pattern_escape(s)
return (string.gsub(s, "([%^%$%(%)%%%.%[%]%*%+%-%?])", "%%%1"))
end
--- The stored token was already URL encoded by secure_value, so it comes back
--- verbatim and the write path in set_cookie stays symmetric with this read
--- path. Decoding it here would break the signature check for any value
--- carrying a percent escape.
---
--- The name is escaped because it lands in a pattern. A cookie_name holding a
--- magic character, say "cgit-auth", would otherwise read as a pattern and stop
--- matching its own cookie while matching names nobody configured.
+-- The token comes back still URL encoded by secure_value. Decoding it here
+-- would break the signature check for any value carrying a percent escape.
+-- The name is escaped because it lands in a Lua pattern.
function get_cookie(cookies, name)
cookies = string.gsub(";" .. (cookies or "") .. ";", "%s*;%s*", ";")
return string.match(cookies, ";" .. pattern_escape(name) .. "=(.-);")
@@ -516,18 +498,21 @@ function body()
html_attr(secure_value("redirect", target, 0))
html("'>")
html("<table>")
- html("<tr><td><label for='username'>Username:</label></td><td><input id='username' name='username' autocomplete='username' autofocus></td></tr>")
- html("<tr><td><label for='password'>Password:</label></td><td><input id='password' name='password' type='password' autocomplete='current-password'></td></tr>")
- html("<tr><td colspan='2'><input value='Login' type='submit'></td></tr>")
+ html("<tr><td><label for='username'>Username:</label></td><td>")
+ html("<input id='username' name='username'")
+ html(" autocomplete='username' autofocus></td></tr>")
+ html("<tr><td><label for='password'>Password:</label></td><td>")
+ html("<input id='password' name='password' type='password'")
+ html(" autocomplete='current-password'></td></tr>")
+ html("<tr><td colspan='2'>")
+ html("<input value='Login' type='submit'></td></tr>")
html("</table></form>")
return 0
end
--- cgit calls filter_open with the action name followed by the request fields
--- in a fixed order, so they are unpacked here into the tables the functions
--- above read. Only a post reaches filter_write, carrying the form body, and
--- filter_close is where the action finally runs and answers cgit.
+-- filter_open unpacks the action and request fields cgit passes in fixed
+-- order, filter_write collects a post body, and filter_close runs the action.
local actions = {}
actions["authenticate-post"] = authenticate_post