diff options
Diffstat (limited to 'filters/gentoo-ldap-authentication.lua')
-rw-r--r-- | filters/gentoo-ldap-authentication.lua | 53 |
1 files changed, 43 insertions, 10 deletions
diff --git a/filters/gentoo-ldap-authentication.lua b/filters/gentoo-ldap-authentication.lua index 3b6564b..b4d98c2 100644 --- a/filters/gentoo-ldap-authentication.lua +++ b/filters/gentoo-ldap-authentication.lua @@ -5,7 +5,13 @@ -- <http://mkottman.github.io/luacrypto/> -- lualdap >= 1.2 -- <https://git.zx2c4.com/lualdap/about/> +-- luaposix +-- <https://github.com/luaposix/luaposix> -- +local sysstat = require("posix.sys.stat") +local unistd = require("posix.unistd") +local crypto = require("crypto") +local lualdap = require("lualdap") -- @@ -21,11 +27,9 @@ local protected_repos = { portage = "dev" } - --- All cookies will be authenticated based on this secret. Make it something --- totally random and impossible to guess. It should be large. -local secret = "BE SURE TO CUSTOMIZE THIS STRING TO SOMETHING BIG AND RANDOM" - +-- Set this to a path this script can write to for storing a persistent +-- cookie secret, which should be guarded. +local secret_filename = "/var/cache/cgit/auth-secret" -- @@ -102,8 +106,6 @@ end -- -- -local lualdap = require("lualdap") - function gentoo_ldap_user_groups(username, password) -- Ensure the user is alphanumeric if username == nil or username:match("%W") then @@ -231,7 +233,38 @@ end -- -- -local crypto = require("crypto") +local secret = nil + +-- Loads a secret from a file, creates a secret, or returns one from memory. +function get_secret() + if secret ~= nil then + return secret + end + local secret_file = io.open(secret_filename, "r") + if secret_file == nil then + local old_umask = sysstat.umask(63) + local temporary_filename = secret_filename .. ".tmp." .. crypto.hex(crypto.rand.bytes(16)) + local temporary_file = io.open(temporary_filename, "w") + if temporary_file == nil then + os.exit(177) + end + temporary_file:write(crypto.hex(crypto.rand.bytes(32))) + temporary_file:close() + unistd.link(temporary_filename, secret_filename) -- Intentionally fails in the case that another process is doing the same. + unistd.unlink(temporary_filename) + sysstat.umask(old_umask) + secret_file = io.open(secret_filename, "r") + end + if secret_file == nil then + os.exit(177) + end + secret = secret_file:read() + secret_file:close() + if secret:len() ~= 64 then + os.exit(177) + end + return secret +end -- Returns value of cookie if cookie is valid. Otherwise returns nil. function validate_value(expected_field, cookie) @@ -271,7 +304,7 @@ function validate_value(expected_field, cookie) end -- Lua hashes strings, so these comparisons are time invariant. - if hmac ~= crypto.hmac.digest("sha256", field .. "|" .. value .. "|" .. tostring(expiration) .. "|" .. salt, secret) then + if hmac ~= crypto.hmac.digest("sha256", field .. "|" .. value .. "|" .. tostring(expiration) .. "|" .. salt, get_secret()) then return nil end @@ -296,7 +329,7 @@ function secure_value(field, value, expiration) value = url_encode(value) field = url_encode(field) authstr = field .. "|" .. value .. "|" .. tostring(expiration) .. "|" .. salt - authstr = authstr .. "|" .. crypto.hmac.digest("sha256", authstr, secret) + authstr = authstr .. "|" .. crypto.hmac.digest("sha256", authstr, get_secret()) return authstr end |