diff --git a/debian/changelog b/debian/changelog index 57d2a99..136b90d 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,14 @@ +ssowat (2.7.0) testing; urgency=low + + * [mod] comment didn't matched reality + * [i18n] Started russian translation (#85) + +Thanks to all contributors (Bram, Ozhiganov) ! <3 + + [ Alexandre Aubin ] + + -- Alexandre Aubin Mon, 07 Aug 2017 12:58:39 -0400 + ssowat (2.6.8) testing; urgency=low [ Laurent Peuch ] diff --git a/helpers.lua b/helpers.lua index e8a7787..ea7f67b 100644 --- a/helpers.lua +++ b/helpers.lua @@ -30,7 +30,7 @@ end -- Get the index of a value in a table function index_of(t,val) - for k,v in ipairs(t) do + for k,v in ipairs(t) do if v == val then return k end end end @@ -50,8 +50,8 @@ end -- Find a string by its translate key in the right language function t(key) - if conf.lang and i18n[conf.lang] then - return i18n[conf.lang][key] or "" + if conf.lang and i18n[conf.lang] and i18n[conf.lang][key] then + return i18n[conf.lang][key] else return i18n[conf["default_language"]][key] or "" end @@ -81,7 +81,7 @@ function hmac_sha512(key, message) -- this is really dirty and probably leak the key and the message in the process list -- but if someone got there I guess we really have other problems so this is acceptable -- and also this is way better than the previous situation - local pipe = io.popen("echo -n '" ..message.. "' | openssl sha512 -hmac '" ..key.. "'") + local pipe = io.popen("echo -n '" ..message:gsub("'", "'\\''").. "' | openssl sha512 -hmac '" ..key:gsub("'", "'\\''").. "'") -- openssl returns something like this: -- root@yunohost:~# echo -n "qsd" | openssl sha512 -hmac "key" @@ -147,7 +147,7 @@ function set_auth_cookie(user, domain) "; Path=/".. "; Expires="..os.date("%a, %d %b %Y %X UTC;", expire).. "; Secure" - + ngx.header["Set-Cookie"] = { "SSOwAuthUser="..user..cookie_str, "SSOwAuthHash="..hash..cookie_str, @@ -293,6 +293,7 @@ function authenticate(user, password) -- cache shared table in order to eventually reuse it later when updating -- profile information or just passing credentials to an application. if connected then + ensure_user_password_uses_strong_hash(connected, user, password) cache:add(user.."-password", password, conf["session_timeout"]) ngx.log(ngx.NOTICE, "Connected as: "..user) return user @@ -556,13 +557,8 @@ function get_data_for(view) end -- Pass all the translated strings to the view (to use with t_) - if conf.lang and i18n[conf.lang] then - translate_table = i18n[conf.lang] - else - translate_table = i18n[conf["default_language"]] - end - for k, v in pairs(translate_table) do - data["t_"..k] = v + for k, v in pairs(i18n[conf["default_language"]]) do + data["t_"..k] = (i18n[conf.lang] and i18n[conf.lang][k]) or v end -- Pass flash notification content @@ -573,6 +569,33 @@ function get_data_for(view) return data end +-- this function is launched after a successful login +-- it checked if the user password is stored using the most secure hashing +-- algorithm available +-- if it's not the case, it migrates the password to this new hash algorithm +function ensure_user_password_uses_strong_hash(ldap, user, password) + local current_hashed_password = nil + + for dn, attrs in ldap:search { + base = "ou=users,dc=yunohost,dc=org", + scope = "onelevel", + sizelimit = 1, + filter = "(uid="..user..")", + attrs = {"userPassword"} + } do + current_hashed_password = attrs["userPassword"]:sub(0, 10) + end + + -- if the password is not hashed using sha-512, which is the strongest + -- available hash rehash it using that + -- Here "{CRYPT}" means "uses linux auth system" + -- "6" means "uses sha-512", any lower number mean a less strong algo (1 == md5) + if current_hashed_password:sub(0, 10) ~= "{CRYPT}$6$" then + local dn = conf["ldap_identifier"].."="..user..","..conf["ldap_group"] + local hashed_password = hash_password(password) + ldap:modify(dn, {'=', userPassword = hashed_password }) + end +end -- Compute the user modification POST request -- It has to update cached information and edit the LDAP user entry @@ -607,7 +630,8 @@ function edit_user() -- Open the LDAP connection local ldap = lualdap.open_simple(conf["ldap_host"], dn, args.currentpassword) - local password = "{SHA}"..ngx.encode_base64(ngx.sha1_bin(args.newpassword)) + + local password = hash_password(args.newpassword) -- Modify the LDAP information if ldap:modify(dn, {'=', userPassword = password }) then @@ -808,6 +832,16 @@ function edit_user() end end +-- hash the user password using sha-512 and using {CRYPT} to uses linux auth system +-- because ldap doesn't support anything stronger than sha1 +function hash_password(password) + -- TODO is the password checked by regex? we don't want to + -- allow shell injection + local mkpasswd = io.popen("mkpasswd --method=sha-512 '" ..password:gsub("'", "'\\''").."'") + local hashed_password = "{CRYPT}"..mkpasswd:read() + mkpasswd:close() + return hashed_password +end -- Compute the user login POST request -- It authenticates the user against the LDAP base then redirects to the portal