aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJason A. Donenfeld2015-03-05 15:45:25 +0100
committerJason A. Donenfeld2015-03-05 15:51:22 +0100
commitecd6b7230c88deb23f880ee1df75ae4b230cf9ec (patch)
tree2ac0b03d38e62eb8ee57cb7f7b231a9201e92888
parentbd24832cd7a72117afb7fa785f4e6bfa4324bf30 (diff)
downloadcgit-ecd6b7230c88deb23f880ee1df75ae4b230cf9ec.tar.gz
cgit-ecd6b7230c88deb23f880ee1df75ae4b230cf9ec.tar.bz2
cgit-ecd6b7230c88deb23f880ee1df75ae4b230cf9ec.zip
simple-authentication.lua: tie secure cookies to field names
-rw-r--r--filters/simple-authentication.lua34
1 files changed, 21 insertions, 13 deletions
diff --git a/filters/simple-authentication.lua b/filters/simple-authentication.lua
index cc86b7e..de34d09 100644
--- a/filters/simple-authentication.lua
+++ b/filters/simple-authentication.lua
@@ -46,7 +46,7 @@ local secret = "BE SURE TO CUSTOMIZE THIS STRING TO SOMETHING BIG AND RANDOM"
46-- Sets HTTP cookie headers based on post and sets up redirection. 46-- Sets HTTP cookie headers based on post and sets up redirection.
47function authenticate_post() 47function authenticate_post()
48 local password = users[post["username"]] 48 local password = users[post["username"]]
49 local redirect = validate_value(post["redirect"]) 49 local redirect = validate_value("redirect", post["redirect"])
50 50
51 if redirect == nil then 51 if redirect == nil then
52 not_found() 52 not_found()
@@ -60,7 +60,7 @@ function authenticate_post()
60 set_cookie("cgitauth", "") 60 set_cookie("cgitauth", "")
61 else 61 else
62 -- One week expiration time 62 -- One week expiration time
63 local username = secure_value(post["username"], os.time() + 604800) 63 local username = secure_value("username", post["username"], os.time() + 604800)
64 set_cookie("cgitauth", username) 64 set_cookie("cgitauth", username)
65 end 65 end
66 66
@@ -77,7 +77,7 @@ function authenticate_cookie()
77 return 1 77 return 1
78 end 78 end
79 79
80 local username = validate_value(get_cookie(http["cookie"], "cgitauth")) 80 local username = validate_value("username", get_cookie(http["cookie"], "cgitauth"))
81 if username == nil or not accepted_users[username:lower()] then 81 if username == nil or not accepted_users[username:lower()] then
82 return 0 82 return 0
83 else 83 else
@@ -92,7 +92,7 @@ function body()
92 html_attr(cgit["login"]) 92 html_attr(cgit["login"])
93 html("'>") 93 html("'>")
94 html("<input type='hidden' name='redirect' value='") 94 html("<input type='hidden' name='redirect' value='")
95 html_attr(secure_value(cgit["url"], 0)) 95 html_attr(secure_value("redirect", cgit["url"], 0))
96 html("' />") 96 html("' />")
97 html("<table>") 97 html("<table>")
98 html("<tr><td><label for='username'>Username:</label></td><td><input id='username' name='username' autofocus /></td></tr>") 98 html("<tr><td><label for='username'>Username:</label></td><td><input id='username' name='username' autofocus /></td></tr>")
@@ -194,9 +194,10 @@ end
194local crypto = require("crypto") 194local crypto = require("crypto")
195 195
196-- Returns value of cookie if cookie is valid. Otherwise returns nil. 196-- Returns value of cookie if cookie is valid. Otherwise returns nil.
197function validate_value(cookie) 197function validate_value(expected_field, cookie)
198 local i = 0 198 local i = 0
199 local value = "" 199 local value = ""
200 local field = ""
200 local expiration = 0 201 local expiration = 0
201 local salt = "" 202 local salt = ""
202 local hmac = "" 203 local hmac = ""
@@ -207,15 +208,17 @@ function validate_value(cookie)
207 208
208 for component in string.gmatch(cookie, "[^|]+") do 209 for component in string.gmatch(cookie, "[^|]+") do
209 if i == 0 then 210 if i == 0 then
210 value = component 211 field = component
211 elseif i == 1 then 212 elseif i == 1 then
213 value = component
214 elseif i == 2 then
212 expiration = tonumber(component) 215 expiration = tonumber(component)
213 if expiration == nil then 216 if expiration == nil then
214 expiration = 0 217 expiration = -1
215 end 218 end
216 elseif i == 2 then
217 salt = component
218 elseif i == 3 then 219 elseif i == 3 then
220 salt = component
221 elseif i == 4 then
219 hmac = component 222 hmac = component
220 else 223 else
221 break 224 break
@@ -228,18 +231,22 @@ function validate_value(cookie)
228 end 231 end
229 232
230 -- Lua hashes strings, so these comparisons are time invariant. 233 -- Lua hashes strings, so these comparisons are time invariant.
231 if hmac ~= crypto.hmac.digest("sha1", value .. "|" .. tostring(expiration) .. "|" .. salt, secret) then 234 if hmac ~= crypto.hmac.digest("sha1", field .. "|" .. value .. "|" .. tostring(expiration) .. "|" .. salt, secret) then
235 return nil
236 end
237
238 if expiration == -1 or (expiration ~= 0 and expiration <= os.time()) then
232 return nil 239 return nil
233 end 240 end
234 241
235 if expiration ~= 0 and expiration <= os.time() then 242 if url_decode(field) ~= expected_field then
236 return nil 243 return nil
237 end 244 end
238 245
239 return url_decode(value) 246 return url_decode(value)
240end 247end
241 248
242function secure_value(value, expiration) 249function secure_value(field, value, expiration)
243 if value == nil or value:len() <= 0 then 250 if value == nil or value:len() <= 0 then
244 return "" 251 return ""
245 end 252 end
@@ -247,7 +254,8 @@ function secure_value(value, expiration)
247 local authstr = "" 254 local authstr = ""
248 local salt = crypto.hex(crypto.rand.bytes(16)) 255 local salt = crypto.hex(crypto.rand.bytes(16))
249 value = url_encode(value) 256 value = url_encode(value)
250 authstr = value .. "|" .. tostring(expiration) .. "|" .. salt 257 field = url_encode(field)
258 authstr = field .. "|" .. value .. "|" .. tostring(expiration) .. "|" .. salt
251 authstr = authstr .. "|" .. crypto.hmac.digest("sha1", authstr, secret) 259 authstr = authstr .. "|" .. crypto.hmac.digest("sha1", authstr, secret)
252 return authstr 260 return authstr
253end 261end