From 90425c2559ab4c204e3c7018efa522dd2cb7ba9b Mon Sep 17 00:00:00 2001 From: Alejandro Huertas Date: Fri, 1 Mar 2019 12:30:24 +0100 Subject: [PATCH] F #2899: Replace SHA1 by SHA256 * Add new SHA256 hashing function * Change user password from SHA1 to SHA256 automatically --- include/AuthRequest.h | 3 ++- include/Image.h | 6 +++--- include/NebulaUtil.h | 9 ++++++++- .../server_cipher/server_cipher_auth.rb | 4 ++-- src/cli/one_helper/oneuser_helper.rb | 6 +++--- src/cli/oneuser | 11 +++++------ .../common/CloudAuth/SunstoneCloudAuth.rb | 4 ++-- src/common/NebulaUtil.cc | 19 ++++++++++++++++++- src/sunstone/sunstone-server.rb | 2 +- src/um/User.cc | 2 +- src/um/UserPool.cc | 18 ++++++++++++++++-- 11 files changed, 61 insertions(+), 23 deletions(-) diff --git a/include/AuthRequest.h b/include/AuthRequest.h index 5290f44f00..4d4e36e3b6 100644 --- a/include/AuthRequest.h +++ b/include/AuthRequest.h @@ -168,8 +168,9 @@ public: bool core_authenticate() { string sha1_session = one_util::sha1_digest(session); + string sha256_session = one_util::sha256_digest(session); - return (password == sha1_session); + return (password == sha1_session) || (password == sha256_session); } private: diff --git a/include/Image.h b/include/Image.h index b8207c4474..5d000c6837 100644 --- a/include/Image.h +++ b/include/Image.h @@ -707,11 +707,11 @@ private: }; /** - * "Encrypts" the password with SHA1 digest + * "Encrypts" the password with SHA256 digest * @param password - * @return sha1 encrypted password + * @return sha256 encrypted password */ - static string sha1_digest(const string& pass); + static string sha256_digest(const string& pass); protected: diff --git a/include/NebulaUtil.h b/include/NebulaUtil.h index e350812b50..c8864d0a94 100644 --- a/include/NebulaUtil.h +++ b/include/NebulaUtil.h @@ -49,7 +49,14 @@ namespace one_util */ std::string sha1_digest(const std::string& in); - /** + /** + * sha256 digest + * @param in the string to be hashed + * @return sha256 hash of str + */ + std::string sha256_digest(const std::string& in); + + /** * Base 64 encoding * @param in the string to encoded * @return a pointer to the encoded string (must be freed) or 0 in case of diff --git a/src/authm_mad/remotes/server_cipher/server_cipher_auth.rb b/src/authm_mad/remotes/server_cipher/server_cipher_auth.rb index c3dc0c78c1..8283d29978 100644 --- a/src/authm_mad/remotes/server_cipher/server_cipher_auth.rb +++ b/src/authm_mad/remotes/server_cipher/server_cipher_auth.rb @@ -15,7 +15,7 @@ #--------------------------------------------------------------------------- # require 'openssl' -require 'digest/sha1' +require 'digest/sha2' require 'base64' require 'fileutils' @@ -40,7 +40,7 @@ class OpenNebula::ServerCipherAuth if !srv_passwd.empty? # truncate token to 32-bytes for Ruby >= 2.4 - @key = Digest::SHA1.hexdigest(@srv_passwd)[0..31] + @key = Digest::SHA256.hexdigest(@srv_passwd)[0..31] else @key = "" end diff --git a/src/cli/one_helper/oneuser_helper.rb b/src/cli/one_helper/oneuser_helper.rb index efaea94379..0f603ac964 100644 --- a/src/cli/one_helper/oneuser_helper.rb +++ b/src/cli/one_helper/oneuser_helper.rb @@ -65,9 +65,9 @@ class OneUserHelper < OpenNebulaHelper::OneHelper password = OpenNebula::X509Auth.escape_dn(password) end - if options[:sha1] || options[:driver] == OpenNebula::User::CIPHER_AUTH - require 'digest/sha1' - password = Digest::SHA1.hexdigest(password) + if options[:sha256] || options[:driver] == OpenNebula::User::CIPHER_AUTH + require 'digest/sha2' + password = Digest::SHA256.hexdigest(password) end return 0, password diff --git a/src/cli/oneuser b/src/cli/oneuser index fd3bd2de53..d6d85754c4 100755 --- a/src/cli/oneuser +++ b/src/cli/oneuser @@ -72,11 +72,10 @@ CommandParser::CmdParser.new(ARGV) do :description => 'Read password from file' } - SHA1 = { - :name => 'sha1', - :large => '--sha1', - :description => "The password will be hashed using the sha1\n" \ - ' ' * 31 << 'algorithm' + SHA256 = { + :name => 'sha256', + :large => '--sha256', + :description => 'The password will be hashed using the sha256 algorithm' } SSH = { @@ -203,7 +202,7 @@ CommandParser::CmdParser.new(ARGV) do :description => 'enable stdin password' } - auth_options = [READ_FILE, SHA1, SSH, X509, KEY, CERT, DRIVER] + auth_options = [READ_FILE, SHA256, SSH, X509, KEY, CERT, DRIVER] create_options = auth_options.clone.unshift(GROUP_CREATE) diff --git a/src/cloud/common/CloudAuth/SunstoneCloudAuth.rb b/src/cloud/common/CloudAuth/SunstoneCloudAuth.rb index 440eb5f251..ddeb89993d 100644 --- a/src/cloud/common/CloudAuth/SunstoneCloudAuth.rb +++ b/src/cloud/common/CloudAuth/SunstoneCloudAuth.rb @@ -23,11 +23,11 @@ module SunstoneCloudAuth one_pass = get_password(username, 'core') - if one_pass && one_pass == Digest::SHA1.hexdigest(password) + if one_pass && one_pass == Digest::SHA256.hexdigest(password) return username end end return nil end -end \ No newline at end of file +end diff --git a/src/common/NebulaUtil.cc b/src/common/NebulaUtil.cc index 39ad93fdf7..bfc174a933 100644 --- a/src/common/NebulaUtil.cc +++ b/src/common/NebulaUtil.cc @@ -211,6 +211,23 @@ string one_util::sha1_digest(const string& in) /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ +string one_util::sha256_digest(const string& in) +{ + unsigned char digest[SHA256_DIGEST_LENGTH]; + stringstream oss; + + SHA256((unsigned char*) in.c_str(), in.length(), digest); + + for(int i = 0; i < SHA256_DIGEST_LENGTH; i++) + oss << setfill('0') << setw(2) << hex << nouppercase + << (unsigned int) digest[i]; + + return oss.str(); +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + string * one_util::aes256cbc_encrypt(const string& in, const string password) { EVP_CIPHER_CTX *ctx; @@ -262,7 +279,7 @@ string one_util::random_password() sstr << rand(); - return sha1_digest(sstr.str()); + return sha256_digest(sstr.str()); } /* -------------------------------------------------------------------------- */ diff --git a/src/sunstone/sunstone-server.rb b/src/sunstone/sunstone-server.rb index b0504226e3..32d5e530ab 100755 --- a/src/sunstone/sunstone-server.rb +++ b/src/sunstone/sunstone-server.rb @@ -281,7 +281,7 @@ helpers do session[:display_name] = user[DISPLAY_NAME_XPATH] || user['NAME'] csrftoken_plain = Time.now.to_f.to_s + SecureRandom.base64 - session[:csrftoken] = Digest::MD5.hexdigest(csrftoken_plain) + session[:csrftoken] = Digest::SHA256.hexdigest(csrftoken_plain) group = OpenNebula::Group.new_with_id(OpenNebula::Group::SELF, client) rc = group.info diff --git a/src/um/User.cc b/src/um/User.cc index 1656af6b06..14b2ba0267 100644 --- a/src/um/User.cc +++ b/src/um/User.cc @@ -346,7 +346,7 @@ int User::set_password(const string& passwd, string& error_str) { if (auth_driver == UserPool::CORE_AUTH) { - password = one_util::sha1_digest(passwd); + password = one_util::sha256_digest(passwd); } else { diff --git a/src/um/UserPool.cc b/src/um/UserPool.cc index 960efc5b28..dc7926d3b4 100644 --- a/src/um/UserPool.cc +++ b/src/um/UserPool.cc @@ -173,7 +173,7 @@ UserPool::UserPool(SqlDB * db, allocate(&server_uid, SERVER_NAME, GroupPool::ONEADMIN_ID, - one_util::sha1_digest(random), + one_util::sha256_digest(random), "server_cipher", true, gids, @@ -374,7 +374,7 @@ int UserPool::allocate ( if (auth_driver == UserPool::CORE_AUTH) { - upass = one_util::sha1_digest(password); + upass = one_util::sha256_digest(password); } if (gids.empty()) @@ -661,6 +661,19 @@ bool UserPool::authenticate_internal(User * user, AuthRequest ar(user_id, group_ids); + // ------------------------------------------------------------------------- + // Update SHA1 to SHA256 + // ------------------------------------------------------------------------- + if (password == one_util::sha1_digest(token)) + { + int rc = user->set_password(token, error_str); + + if ( rc == 0 ) + { + update(user); + } + } + // ------------------------------------------------------------------------- // Check if token is a login or session token, and set EGID if needed // ------------------------------------------------------------------------- @@ -704,6 +717,7 @@ bool UserPool::authenticate_internal(User * user, } user->unlock(); + // ------------------------------------------------------------------------- // Not a valid token, perform authentication // -------------------------------------------------------------------------