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"')

Impressum / About Us