about summary refs log tree commit diff stats
path: root/filters
diff options
context:
space:
mode:
authorJason A. Donenfeld2018-07-15 03:22:12 +0200
committerJason A. Donenfeld2018-07-15 03:30:57 +0200
commitb73df8098f261ecbd4bc5ba689f9766a1a75f9a0 (patch)
treeaebcaab97994951531547194cf9f51ba353dd4ad /filters
parentauth-filters: do not crash on nil username (diff)
downloadcgit-b73df8098f261ecbd4bc5ba689f9766a1a75f9a0.tar.gz
cgit-b73df8098f261ecbd4bc5ba689f9766a1a75f9a0.zip
auth-filters: generate secret securely
This is much better than having the user generate it themselves.

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Diffstat (limited to 'filters')
-rw-r--r--filters/gentoo-ldap-authentication.lua53
-rw-r--r--filters/simple-authentication.lua50
2 files changed, 85 insertions, 18 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 @@
5-- <http://mkottman.github.io/luacrypto/> 5-- <http://mkottman.github.io/luacrypto/>
6-- lualdap >= 1.2 6-- lualdap >= 1.2
7-- <https://git.zx2c4.com/lualdap/about/> 7-- <https://git.zx2c4.com/lualdap/about/>
8-- luaposix
9-- <https://github.com/luaposix/luaposix>
8-- 10--
11local sysstat = require("posix.sys.stat")
12local unistd = require("posix.unistd")
13local crypto = require("crypto")
14local lualdap = require("lualdap")
9 15
10 16
11-- 17--
@@ -21,11 +27,9 @@ local protected_repos = {
21 portage = "dev" 27 portage = "dev"
22} 28}
23 29
24 30-- Set this to a path this script can write to for storing a persistent
25-- All cookies will be authenticated based on this secret. Make it something 31-- cookie secret, which should be guarded.
26-- totally random and impossible to guess. It should be large. 32local secret_filename = "/var/cache/cgit/auth-secret"
27local secret = "BE SURE TO CUSTOMIZE THIS STRING TO SOMETHING BIG AND RANDOM"
28
29 33
30 34
31-- 35--
@@ -102,8 +106,6 @@ end
102-- 106--
103-- 107--
104 108
105local lualdap = require("lualdap")
106
107function gentoo_ldap_user_groups(username, password) 109function gentoo_ldap_user_groups(username, password)
108 -- Ensure the user is alphanumeric 110 -- Ensure the user is alphanumeric
109 if username == nil or username:match("%W") then 111 if username == nil or username:match("%W") then
@@ -231,7 +233,38 @@ end
231-- 233--
232-- 234--
233 235
234local crypto = require("crypto") 236local secret = nil
237
238-- Loads a secret from a file, creates a secret, or returns one from memory.
239function get_secret()
240 if secret ~= nil then
241 return secret
242 end
243 local secret_file = io.open(secret_filename, "r")
244 if secret_file == nil then
245 local old_umask = sysstat.umask(63)
246 local temporary_filename = secret_filename .. ".tmp." .. crypto.hex(crypto.rand.bytes(16))
247 local temporary_file = io.open(temporary_filename, "w")
248 if temporary_file == nil then
249 os.exit(177)
250 end
251 temporary_file:write(crypto.hex(crypto.rand.bytes(32)))
252 temporary_file:close()
253 unistd.link(temporary_filename, secret_filename) -- Intentionally fails in the case that another process is doing the same.
254 unistd.unlink(temporary_filename)
255 sysstat.umask(old_umask)
256 secret_file = io.open(secret_filename, "r")
257 end
258 if secret_file == nil then
259 os.exit(177)
260 end
261 secret = secret_file:read()
262 secret_file:close()
263 if secret:len() ~= 64 then
264 os.exit(177)
265 end
266 return secret
267end
235 268
236-- Returns value of cookie if cookie is valid. Otherwise returns nil. 269-- Returns value of cookie if cookie is valid. Otherwise returns nil.
237function validate_value(expected_field, cookie) 270function validate_value(expected_field, cookie)
@@ -271,7 +304,7 @@ function validate_value(expected_field, cookie)
271 end 304 end
272 305
273 -- Lua hashes strings, so these comparisons are time invariant. 306 -- Lua hashes strings, so these comparisons are time invariant.
274 if hmac ~= crypto.hmac.digest("sha256", field .. "|" .. value .. "|" .. tostring(expiration) .. "|" .. salt, secret) then 307 if hmac ~= crypto.hmac.digest("sha256", field .. "|" .. value .. "|" .. tostring(expiration) .. "|" .. salt, get_secret()) then
275 return nil 308 return nil
276 end 309 end
277 310
@@ -296,7 +329,7 @@ function secure_value(field, value, expiration)
296 value = url_encode(value) 329 value = url_encode(value)
297 field = url_encode(field) 330 field = url_encode(field)
298 authstr = field .. "|" .. value .. "|" .. tostring(expiration) .. "|" .. salt 331 authstr = field .. "|" .. value .. "|" .. tostring(expiration) .. "|" .. salt
299 authstr = authstr .. "|" .. crypto.hmac.digest("sha256", authstr, secret) 332 authstr = authstr .. "|" .. crypto.hmac.digest("sha256", authstr, get_secret())
300 return authstr 333 return authstr
301end 334end
302 335
diff --git a/filters/simple-authentication.lua b/filters/simple-authentication.lua index 596c041..bf35632 100644 --- a/filters/simple-authentication.lua +++ b/filters/simple-authentication.lua
@@ -3,7 +3,12 @@
3-- Requirements: 3-- Requirements:
4-- luacrypto >= 0.3 4-- luacrypto >= 0.3
5-- <http://mkottman.github.io/luacrypto/> 5-- <http://mkottman.github.io/luacrypto/>
6-- luaposix
7-- <https://github.com/luaposix/luaposix>
6-- 8--
9local sysstat = require("posix.sys.stat")
10local unistd = require("posix.unistd")
11local crypto = require("crypto")
7 12
8 13
9-- 14--
@@ -31,11 +36,9 @@ local users = {
31 bob = "ilikelua" 36 bob = "ilikelua"
32} 37}
33 38
34-- All cookies will be authenticated based on this secret. Make it something 39-- Set this to a path this script can write to for storing a persistent
35-- totally random and impossible to guess. It should be large. 40-- cookie secret, which should be guarded.
36local secret = "BE SURE TO CUSTOMIZE THIS STRING TO SOMETHING BIG AND RANDOM" 41local secret_filename = "/var/cache/cgit/auth-secret"
37
38
39 42
40-- 43--
41-- 44--
@@ -191,7 +194,38 @@ end
191-- 194--
192-- 195--
193 196
194local crypto = require("crypto") 197local secret = nil
198
199-- Loads a secret from a file, creates a secret, or returns one from memory.
200function get_secret()
201 if secret ~= nil then
202 return secret
203 end
204 local secret_file = io.open(secret_filename, "r")
205 if secret_file == nil then
206 local old_umask = sysstat.umask(63)
207 local temporary_filename = secret_filename .. ".tmp." .. crypto.hex(crypto.rand.bytes(16))
208 local temporary_file = io.open(temporary_filename, "w")
209 if temporary_file == nil then
210 os.exit(177)
211 end
212 temporary_file:write(crypto.hex(crypto.rand.bytes(32)))
213 temporary_file:close()
214 unistd.link(temporary_filename, secret_filename) -- Intentionally fails in the case that another process is doing the same.
215 unistd.unlink(temporary_filename)
216 sysstat.umask(old_umask)
217 secret_file = io.open(secret_filename, "r")
218 end
219 if secret_file == nil then
220 os.exit(177)
221 end
222 secret = secret_file:read()
223 secret_file:close()
224 if secret:len() ~= 64 then
225 os.exit(177)
226 end
227 return secret
228end
195 229
196-- Returns value of cookie if cookie is valid. Otherwise returns nil. 230-- Returns value of cookie if cookie is valid. Otherwise returns nil.
197function validate_value(expected_field, cookie) 231function validate_value(expected_field, cookie)
@@ -231,7 +265,7 @@ function validate_value(expected_field, cookie)
231 end 265 end
232 266
233 -- Lua hashes strings, so these comparisons are time invariant. 267 -- Lua hashes strings, so these comparisons are time invariant.
234 if hmac ~= crypto.hmac.digest("sha256", field .. "|" .. value .. "|" .. tostring(expiration) .. "|" .. salt, secret) then 268 if hmac ~= crypto.hmac.digest("sha256", field .. "|" .. value .. "|" .. tostring(expiration) .. "|" .. salt, get_secret()) then
235 return nil 269 return nil
236 end 270 end
237 271
@@ -256,7 +290,7 @@ function secure_value(field, value, expiration)
256 value = url_encode(value) 290 value = url_encode(value)
257 field = url_encode(field) 291 field = url_encode(field)
258 authstr = field .. "|" .. value .. "|" .. tostring(expiration) .. "|" .. salt 292 authstr = field .. "|" .. value .. "|" .. tostring(expiration) .. "|" .. salt
259 authstr = authstr .. "|" .. crypto.hmac.digest("sha256", authstr, secret) 293 authstr = authstr .. "|" .. crypto.hmac.digest("sha256", authstr, get_secret())
260 return authstr 294 return authstr
261end 295end
262 296