liquid_feedback_frontend
changeset 905:e3887fea39fa
Added support for SHA-2 based password hashing
author | bsw |
---|---|
date | Sun Sep 23 14:35:20 2012 +0200 (2012-09-23) |
parents | a176129ce282 |
children | a2c5707035ea |
files | app/main/index/_action/login.lua config/example.lua config/init.lua model/member.lua |
line diff
1.1 --- a/app/main/index/_action/login.lua Sun Aug 26 22:37:49 2012 +0200 1.2 +++ b/app/main/index/_action/login.lua Sun Sep 23 14:35:20 2012 +0200 1.3 @@ -1,4 +1,7 @@ 1.4 -local member = Member:by_login_and_password(param.get('login'), param.get('password')) 1.5 +local login = param.get("login") 1.6 +local password = param.get("password") 1.7 + 1.8 +local member = Member:by_login_and_password(login, password) 1.9 1.10 function do_etherpad_auth(member) 1.11 local result = net.curl( 1.12 @@ -59,6 +62,11 @@ 1.13 else 1.14 app.session.lang = member.lang 1.15 end 1.16 + 1.17 + if member.password_hash_needs_update then 1.18 + member:set_password(password) 1.19 + end 1.20 + 1.21 member:save() 1.22 app.session.member = member 1.23 app.session:save()
2.1 --- a/config/example.lua Sun Aug 26 22:37:49 2012 +0200 2.2 +++ b/config/example.lua Sun Sep 23 14:35:20 2012 +0200 2.3 @@ -99,6 +99,19 @@ 2.4 -- config.mail_from = { name = "LiquidFeedback", address = "liquidfeedback@example.com" } 2.5 -- config.mail_reply_to = { name = "Support", address = "support@example.com" } 2.6 2.7 +-- Configuration of password hashing algorithm (defaults to "crypt_sha512") 2.8 +-- ------------------------------------------------------------------------ 2.9 +-- config.password_hash_algorithm = "crypt_sha512" 2.10 +-- config.password_hash_algorithm = "crypt_sha256" 2.11 +-- config.password_hash_algorithm = "crypt_md5" 2.12 + 2.13 +-- Number of rounds for crypt_sha* algorithms, minimum and maximum 2.14 +-- (defaults to minimum 10000 and maximum 20000) 2.15 +-- ------------------------------------------------------------------------ 2.16 +-- config.password_hash_min_rounds = 10000 2.17 +-- config.password_hash_max_rounds = 20000 2.18 + 2.19 + 2.20 -- Supply custom url for avatar/photo delivery 2.21 -- ------------------------------------------------------------------------ 2.22 -- config.fastpath_url_func = nil
3.1 --- a/config/init.lua Sun Aug 26 22:37:49 2012 +0200 3.2 +++ b/config/init.lua Sun Sep 23 14:35:20 2012 +0200 3.3 @@ -5,6 +5,18 @@ 3.4 3.5 config.app_version = "2.0.5" 3.6 3.7 +if not config.password_hash_algorithm then 3.8 + config.password_hash_algorithm = "crypt_sha512" 3.9 +end 3.10 + 3.11 +if not config.password_hash_min_rounds then 3.12 + config.password_hash_min_rounds = 10000 3.13 +end 3.14 + 3.15 +if not config.password_hash_max_rounds then 3.16 + config.password_hash_max_rounds = 20000 3.17 +end 3.18 + 3.19 if config.enabled_languages == nil then 3.20 config.enabled_languages = { 'en', 'de', 'eo', 'el', 'hu', 'it', 'nl', 'zh-Hans', 'zh-TW' } 3.21 end
4.1 --- a/model/member.lua Sun Aug 26 22:37:49 2012 +0200 4.2 +++ b/model/member.lua Sun Sep 23 14:35:20 2012 +0200 4.3 @@ -271,14 +271,46 @@ 4.4 4.5 function Member.object:set_password(password) 4.6 trace.disable() 4.7 + 4.8 + local hash_prefix 4.9 + local salt_length 4.10 + 4.11 + local function rounds() 4.12 + return multirand.integer( 4.13 + config.password_hash_min_rounds, 4.14 + config.password_hash_max_rounds 4.15 + ) 4.16 + end 4.17 + 4.18 + if config.password_hash_algorithm == "crypt_md5" then 4.19 + hash_prefix = "$1$" 4.20 + salt_length = 8 4.21 + 4.22 + elseif config.password_hash_algorithm == "crypt_sha256" then 4.23 + hash_prefix = "$5$rounds=" .. rounds() .. "$" 4.24 + salt_length = 16 4.25 + 4.26 + elseif config.password_hash_algorithm == "crypt_sha512" then 4.27 + hash_prefix = "$6$rounds=" .. rounds() .. "$" 4.28 + salt_length = 16 4.29 + 4.30 + else 4.31 + error("Unknown hash algorithm selected in configuration") 4.32 + 4.33 + end 4.34 + 4.35 local hash = extos.crypt( 4.36 password, 4.37 - "$1$" .. multirand.string( 4.38 - 8, 4.39 + hash_prefix .. multirand.string( 4.40 + salt_length, 4.41 "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz./" 4.42 ) 4.43 ) 4.44 - assert(hash, "extos.crypt failed") 4.45 + 4.46 + if not hash or hash:sub(1, #hash_prefix) ~= hash_prefix then 4.47 + error("Password hashing algorithm failed") 4.48 + end 4.49 + 4.50 self.password = hash 4.51 end 4.52 4.53 @@ -290,6 +322,44 @@ 4.54 end 4.55 end 4.56 4.57 +function Member.object_get:password_hash_needs_update() 4.58 + 4.59 + if self.password == nil then 4.60 + return nil 4.61 + end 4.62 + 4.63 + local function check_rounds(rounds) 4.64 + if rounds then 4.65 + rounds = tonumber(rounds) 4.66 + if 4.67 + rounds >= config.password_hash_min_rounds and 4.68 + rounds <= config.password_hash_max_rounds 4.69 + then 4.70 + return false 4.71 + end 4.72 + end 4.73 + return true 4.74 + end 4.75 + 4.76 + if config.password_hash_algorithm == "crypt_md5" then 4.77 + 4.78 + return self.password:sub(1,3) ~= "$1$" 4.79 + 4.80 + elseif config.password_hash_algorithm == "crypt_sha256" then 4.81 + 4.82 + return check_rounds(self.password:match("^%$5%$rounds=([1-9][0-9]*)%$")) 4.83 + 4.84 + elseif config.password_hash_algorithm == "crypt_sha512" then 4.85 + 4.86 + return check_rounds(self.password:match("^%$6%$rounds=([1-9][0-9]*)%$")) 4.87 + 4.88 + else 4.89 + error("Unknown hash algorithm selected in configuration") 4.90 + 4.91 + end 4.92 + 4.93 +end 4.94 + 4.95 function Member.object_get:published_contacts() 4.96 return Member:new_selector() 4.97 :join('"contact"', nil, '"contact"."other_member_id" = "member"."id"')