From b95a9002b5e80af68d13d69143695ecb779ddea6 Mon Sep 17 00:00:00 2001 From: Rajkumar Date: Mon, 7 Feb 2022 13:17:21 -0800 Subject: [PATCH 1/3] Clang-Tidy Issue --- src/Processors/Formats/Impl/TSKVRowInputFormat.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Processors/Formats/Impl/TSKVRowInputFormat.cpp b/src/Processors/Formats/Impl/TSKVRowInputFormat.cpp index eef97e15dd5b..31d1d143b44e 100644 --- a/src/Processors/Formats/Impl/TSKVRowInputFormat.cpp +++ b/src/Processors/Formats/Impl/TSKVRowInputFormat.cpp @@ -17,7 +17,7 @@ namespace ErrorCodes TSKVRowInputFormat::TSKVRowInputFormat(ReadBuffer & in_, Block header_, Params params_, const FormatSettings & format_settings_) - : IRowInputFormat(std::move(header_), in_, std::move(params_)), format_settings(format_settings_), name_map(header_.columns()) + : IRowInputFormat(header_, in_, std::move(params_)), format_settings(format_settings_), name_map(header_.columns()) { const auto & sample_block = getPort().getHeader(); size_t num_columns = sample_block.columns(); From 3522f519365eb90c50434045f36c789636251c5c Mon Sep 17 00:00:00 2001 From: Rajkumar Date: Tue, 29 Mar 2022 17:37:32 -0700 Subject: [PATCH 2/3] salt hash password feature --- src/Access/AccessEntityIO.cpp | 13 ++++ src/Access/Authentication.cpp | 41 +++++++++-- src/Access/Common/AuthenticationData.cpp | 68 ++++++++++++++++++- src/Access/Common/AuthenticationData.h | 18 +++++ src/Access/IAccessStorage.cpp | 20 +++++- src/Access/IAccessStorage.h | 8 +-- .../Access/InterpreterCreateUserQuery.cpp | 15 ++++ src/Parsers/Access/ASTCreateUserQuery.cpp | 12 ++++ src/Parsers/Access/ParserCreateUserQuery.cpp | 13 +++- .../0_stateless/01292_create_user.reference | 2 + .../queries/0_stateless/01292_create_user.sql | 7 +- 11 files changed, 198 insertions(+), 19 deletions(-) diff --git a/src/Access/AccessEntityIO.cpp b/src/Access/AccessEntityIO.cpp index e944dc711144..d1d7118a7f70 100644 --- a/src/Access/AccessEntityIO.cpp +++ b/src/Access/AccessEntityIO.cpp @@ -86,6 +86,16 @@ String serializeAccessEntity(const IAccessEntity & entity) for (const ASTPtr & query : queries) { formatAST(*query, buf, false, true); + if (const User * user = typeid_cast(&entity)) + { + if(user->auth_data.getSaltEnabledStatus()) + { + std::string strSalt = " '"; + strSalt += user->auth_data.getSalt(); + strSalt+="'"; + buf.write(strSalt.c_str(), strSalt.length()); + } + } buf.write(";\n", 2); } return buf.str(); @@ -121,6 +131,9 @@ AccessEntityPtr deserializeAccessEntity(const String & definition, const String throw Exception("Two access entities attached in " + path, ErrorCodes::INCORRECT_ACCESS_ENTITY_DEFINITION); res = user = std::make_unique(); InterpreterCreateUserQuery::updateUserFromQuery(*user, *create_user_query); + + if(user->auth_data.getSaltEnabledStatus()) + user->auth_data.setPassword(user->auth_data.getPassword() + user->auth_data.getSalt()); } else if (auto * create_role_query = query->as()) { diff --git a/src/Access/Authentication.cpp b/src/Access/Authentication.cpp index 794c0a0d5d59..19c845f1e75a 100644 --- a/src/Access/Authentication.cpp +++ b/src/Access/Authentication.cpp @@ -26,14 +26,33 @@ namespace return (Util::stringToDigest(password) == password_plaintext); } - bool checkPasswordDoubleSHA1(const std::string_view & password, const Digest & password_double_sha1) + bool checkPasswordDoubleSHA1(const std::string_view & password, const Digest & password_double_sha1, bool isSaltEnabled, const String &salt) { - return (Util::encodeDoubleSHA1(password) == password_double_sha1); + if(isSaltEnabled) + { + auto salt_password = salt + std::string(password); + return Util::encodeDoubleSHA1(salt_password) == password_double_sha1; + } + else + { + return Util::encodeDoubleSHA1(password) == password_double_sha1; + } } - bool checkPasswordSHA256(const std::string_view & password, const Digest & password_sha256) + bool checkPasswordSHA256(const std::string_view & password, const Digest & password_sha256, bool isSaltEnabled, const String &salt) { - return Util::encodeSHA256(password) == password_sha256; + if(isSaltEnabled) + { + std::vector salt_password = Util::encodeSHA256(password); + for(auto i : salt) + salt_password.push_back(i); + + return salt_password == password_sha256; + } + else + { + return Util::encodeSHA256(password) == password_sha256; + } } bool checkPasswordDoubleSHA1MySQL(const std::string_view & scramble, const std::string_view & scrambled_password, const Digest & password_double_sha1) @@ -81,6 +100,8 @@ bool Authentication::areCredentialsValid(const Credentials & credentials, const case AuthenticationType::PLAINTEXT_PASSWORD: case AuthenticationType::SHA256_PASSWORD: case AuthenticationType::DOUBLE_SHA1_PASSWORD: + case AuthenticationType::SHA256_PASSWORD_SALT: + case AuthenticationType::DOUBLE_SHA1_PASSWORD_SALT: case AuthenticationType::LDAP: throw Authentication::Require("ClickHouse Basic Authentication"); @@ -106,6 +127,8 @@ bool Authentication::areCredentialsValid(const Credentials & credentials, const return checkPasswordDoubleSHA1MySQL(mysql_credentials->getScramble(), mysql_credentials->getScrambledPassword(), auth_data.getPasswordHashBinary()); case AuthenticationType::SHA256_PASSWORD: + case AuthenticationType::SHA256_PASSWORD_SALT: + case AuthenticationType::DOUBLE_SHA1_PASSWORD_SALT: case AuthenticationType::LDAP: case AuthenticationType::KERBEROS: throw Authentication::Require("ClickHouse Basic Authentication"); @@ -126,10 +149,16 @@ bool Authentication::areCredentialsValid(const Credentials & credentials, const return checkPasswordPlainText(basic_credentials->getPassword(), auth_data.getPasswordHashBinary()); case AuthenticationType::SHA256_PASSWORD: - return checkPasswordSHA256(basic_credentials->getPassword(), auth_data.getPasswordHashBinary()); + return checkPasswordSHA256(basic_credentials->getPassword(), auth_data.getPasswordHashBinary(), auth_data.getSaltEnabledStatus(), auth_data.getSalt()); case AuthenticationType::DOUBLE_SHA1_PASSWORD: - return checkPasswordDoubleSHA1(basic_credentials->getPassword(), auth_data.getPasswordHashBinary()); + return checkPasswordDoubleSHA1(basic_credentials->getPassword(), auth_data.getPasswordHashBinary(), auth_data.getSaltEnabledStatus(), auth_data.getSalt()); + + case AuthenticationType::SHA256_PASSWORD_SALT: + return checkPasswordSHA256(basic_credentials->getPassword(), auth_data.getPasswordHashBinary(), auth_data.getSaltEnabledStatus(), auth_data.getSalt()); + + case AuthenticationType::DOUBLE_SHA1_PASSWORD_SALT: + return checkPasswordDoubleSHA1(basic_credentials->getPassword(), auth_data.getPasswordHashBinary(), auth_data.getSaltEnabledStatus(), auth_data.getSalt()); case AuthenticationType::LDAP: return external_authenticators.checkLDAPCredentials(auth_data.getLDAPServerName(), *basic_credentials); diff --git a/src/Access/Common/AuthenticationData.cpp b/src/Access/Common/AuthenticationData.cpp index 7412d7336e3d..65abb608a6b8 100644 --- a/src/Access/Common/AuthenticationData.cpp +++ b/src/Access/Common/AuthenticationData.cpp @@ -49,6 +49,16 @@ const AuthenticationTypeInfo & AuthenticationTypeInfo::get(AuthenticationType ty static const auto info = make_info("DOUBLE_SHA1_PASSWORD"); return info; } + case AuthenticationType::SHA256_PASSWORD_SALT: + { + static const auto info = make_info("SHA256_PASSWORD_SALT"); + return info; + } + case AuthenticationType::DOUBLE_SHA1_PASSWORD_SALT: + { + static const auto info = make_info("DOUBLE_SHA1_PASSWORD_SALT"); + return info; + } case AuthenticationType::LDAP: { static const auto info = make_info("LDAP"); @@ -59,6 +69,7 @@ const AuthenticationTypeInfo & AuthenticationTypeInfo::get(AuthenticationType ty static const auto info = make_info("KERBEROS"); return info; } + case AuthenticationType::MAX: break; } @@ -104,9 +115,11 @@ void AuthenticationData::setPassword(const String & password_) return setPasswordHashBinary(Util::stringToDigest(password_)); case AuthenticationType::SHA256_PASSWORD: + case AuthenticationType::SHA256_PASSWORD_SALT: return setPasswordHashBinary(Util::encodeSHA256(password_)); case AuthenticationType::DOUBLE_SHA1_PASSWORD: + case AuthenticationType::DOUBLE_SHA1_PASSWORD_SALT: return setPasswordHashBinary(Util::encodeDoubleSHA1(password_)); case AuthenticationType::NO_PASSWORD: @@ -128,6 +141,12 @@ String AuthenticationData::getPassword() const return String(password_hash.data(), password_hash.data() + password_hash.size()); } +String AuthenticationData::getSalt() const +{ + //if (type != AuthenticationType::PLAINTEXT_PASSWORD) + // throw Exception("Cannot decode the password", ErrorCodes::LOGICAL_ERROR); + return String(salt.data(), salt.data() + salt.size()); +} void AuthenticationData::setPasswordHashHex(const String & hash) { @@ -146,7 +165,6 @@ void AuthenticationData::setPasswordHashHex(const String & hash) setPasswordHashBinary(digest); } - String AuthenticationData::getPasswordHashHex() const { if (type == AuthenticationType::LDAP || type == AuthenticationType::KERBEROS) @@ -179,6 +197,11 @@ void AuthenticationData::setPasswordHashBinary(const Digest & hash) password_hash = hash; return; } + case AuthenticationType::SHA256_PASSWORD_SALT: + { + password_hash = hash; + return; + } case AuthenticationType::DOUBLE_SHA1_PASSWORD: { @@ -190,6 +213,11 @@ void AuthenticationData::setPasswordHashBinary(const Digest & hash) password_hash = hash; return; } + case AuthenticationType::DOUBLE_SHA1_PASSWORD_SALT: + { + password_hash = hash; + return; + } case AuthenticationType::NO_PASSWORD: case AuthenticationType::LDAP: @@ -202,4 +230,42 @@ void AuthenticationData::setPasswordHashBinary(const Digest & hash) throw Exception("setPasswordHashBinary(): authentication type " + toString(type) + " not supported", ErrorCodes::NOT_IMPLEMENTED); } +void AuthenticationData::setSaltHashBinary(const Digest & salt_hash) +{ + switch (type) + { + case AuthenticationType::SHA256_PASSWORD_SALT: + case AuthenticationType::DOUBLE_SHA1_PASSWORD_SALT: + { + salt = salt_hash; + return; + } + + default: + throw Exception("Cannot specify salt binary hash for authentication type " + toString(type), ErrorCodes::LOGICAL_ERROR); + } +} + +void AuthenticationData::setSalt(const String & salt_) +{ + switch (type) + { + case AuthenticationType::SHA256_PASSWORD_SALT: + //(salt = salt_); Util::encodeSHA256(salt_);//.data(); + //return; + return setSaltHashBinary(Util::encodeSHA256(salt_)); + case AuthenticationType::DOUBLE_SHA1_PASSWORD_SALT: + //salt = salt_; + //return; + return setSaltHashBinary(Util::encodeDoubleSHA1(salt_)); + default: + throw Exception("setSalt(): authentication type " + toString(type) + " not supported", ErrorCodes::NOT_IMPLEMENTED); + } +} + +void AuthenticationData::setSaltEnableStatus(bool enableSalt) +{ + isSaltEnabled = enableSalt; +} + } diff --git a/src/Access/Common/AuthenticationData.h b/src/Access/Common/AuthenticationData.h index 8b390fd09007..25bd1cd98464 100644 --- a/src/Access/Common/AuthenticationData.h +++ b/src/Access/Common/AuthenticationData.h @@ -28,6 +28,12 @@ enum class AuthenticationType KERBEROS, MAX, + + ///Password hash with salt + SHA256_PASSWORD_SALT, + + ///Double Sha Password hash with salt + DOUBLE_SHA1_PASSWORD_SALT, }; struct AuthenticationTypeInfo @@ -71,6 +77,16 @@ class AuthenticationData void setPasswordHashBinary(const Digest & hash); const Digest & getPasswordHashBinary() const { return password_hash; } + /// Sets the salt in String form. + void setSalt(const String & salt); + void setSaltHashBinary(const Digest & salt_hash); + const Digest& getSaltHashBinary() const { return salt; } + String getSalt() const; + + /// Sets the salt in String form. + void setSaltEnableStatus(bool enableSalt);// { isSaltEnabled = enableSalt; } + const bool & getSaltEnabledStatus() const { return isSaltEnabled; } + /// Sets the server name for authentication type LDAP. const String & getLDAPServerName() const { return ldap_server_name; } void setLDAPServerName(const String & name) { ldap_server_name = name; } @@ -97,6 +113,8 @@ class AuthenticationData Digest password_hash; String ldap_server_name; String kerberos_realm; + Digest salt; + bool isSaltEnabled; }; } diff --git a/src/Access/IAccessStorage.cpp b/src/Access/IAccessStorage.cpp index 51c2525d9236..04c69702b63b 100644 --- a/src/Access/IAccessStorage.cpp +++ b/src/Access/IAccessStorage.cpp @@ -6,14 +6,18 @@ #include #include #include +#include +#include "Poco/HMACEngine.h" +#include "Poco/SHA1Engine.h" #include #include #include #include - +#include namespace DB { + namespace ErrorCodes { extern const int ACCESS_ENTITY_ALREADY_EXISTS; @@ -25,9 +29,9 @@ namespace ErrorCodes extern const int LOGICAL_ERROR; } - namespace { + String outputID(const UUID & id) { return "ID(" + toString(id) + ")"; @@ -472,7 +476,7 @@ UUID IAccessStorage::loginImpl( { if (!isAddressAllowedImpl(*user, address)) throwAddressNotAllowed(address); - + if (!areCredentialsValidImpl(*user, credentials, external_authenticators)) throwInvalidCredentials(); @@ -524,6 +528,16 @@ UUID IAccessStorage::generateRandomID() return id; } +void IAccessStorage::generateSaltDiget(std::string &num) +{ + std::string p("Password"); + std::string s("salt"); + Poco::PBKDF2Engine > pbkdf2(s, 4096, 25); + pbkdf2.update(p); + std::string dk = Poco::DigestEngine::digestToHex(pbkdf2.digest()); + + num=std::move(dk); +} Poco::Logger * IAccessStorage::getLogger() const { diff --git a/src/Access/IAccessStorage.h b/src/Access/IAccessStorage.h index ccbb1ffe5bc6..677f78541667 100644 --- a/src/Access/IAccessStorage.h +++ b/src/Access/IAccessStorage.h @@ -8,8 +8,8 @@ #include #include #include - - +#include +#include namespace Poco { class Logger; } namespace Poco::Net { class IPAddress; } @@ -149,7 +149,6 @@ class IAccessStorage /// Returns the ID of a user who has logged in (maybe on another node). /// The function assumes that the password has been already checked somehow, so we can skip checking it now. UUID getIDOfLoggedUser(const String & user_name) const; - protected: virtual std::optional findImpl(AccessEntityType type, const String & name) const = 0; virtual std::vector findAllImpl(AccessEntityType type) const = 0; @@ -170,6 +169,7 @@ class IAccessStorage virtual UUID getIDOfLoggedUserImpl(const String & user_name) const; static UUID generateRandomID(); + void generateSaltDiget(std::string &); Poco::Logger * getLogger() const; static String formatEntityTypeWithName(AccessEntityType type, const String & name) { return AccessEntityTypeInfo::get(type).formatEntityNameWithType(name); } [[noreturn]] void throwNotFound(const UUID & id) const; @@ -189,7 +189,7 @@ class IAccessStorage using Notification = std::tuple; using Notifications = std::vector; static void notify(const Notifications & notifications); - + private: AccessEntityPtr tryReadBase(const UUID & id) const; diff --git a/src/Interpreters/Access/InterpreterCreateUserQuery.cpp b/src/Interpreters/Access/InterpreterCreateUserQuery.cpp index 33d85afb7c39..6650a448c800 100644 --- a/src/Interpreters/Access/InterpreterCreateUserQuery.cpp +++ b/src/Interpreters/Access/InterpreterCreateUserQuery.cpp @@ -33,6 +33,21 @@ namespace if (query.auth_data) user.auth_data = *query.auth_data; + + user.auth_data.setSaltEnableStatus(false); + + if (query.auth_data->getType() == AuthenticationType::SHA256_PASSWORD_SALT + || query.auth_data->getType() == AuthenticationType::DOUBLE_SHA1_PASSWORD_SALT) + { + //generate and add salt here + String salt = "SALT123"; + user.auth_data.setSalt(salt); + std::vector password = user.auth_data.getPasswordHashBinary(); + std::vector salt_hash = user.auth_data.getSaltHashBinary(); + password.insert(password.end(), salt_hash.begin(), salt_hash.end()); + user.auth_data.setPasswordHashBinary(password); + user.auth_data.setSaltEnableStatus(true); + } if (override_name && !override_name->host_pattern.empty()) { diff --git a/src/Parsers/Access/ASTCreateUserQuery.cpp b/src/Parsers/Access/ASTCreateUserQuery.cpp index 18030a5ed80b..955505a1f740 100644 --- a/src/Parsers/Access/ASTCreateUserQuery.cpp +++ b/src/Parsers/Access/ASTCreateUserQuery.cpp @@ -62,6 +62,18 @@ namespace by_value = auth_data.getPasswordHashHex(); break; } + case AuthenticationType::SHA256_PASSWORD_SALT: + { + auth_type_name = "sha256_hash_salt"; + by_value = auth_data.getPasswordHashHex(); + break; + } + case AuthenticationType::DOUBLE_SHA1_PASSWORD_SALT: + { + auth_type_name = "double_sha1_hash_salt"; + by_value = auth_data.getPasswordHashHex(); + break; + } case AuthenticationType::LDAP: { by_keyword = "SERVER"; diff --git a/src/Parsers/Access/ParserCreateUserQuery.cpp b/src/Parsers/Access/ParserCreateUserQuery.cpp index c5b8c9e37b3b..e7a80adcbd5d 100644 --- a/src/Parsers/Access/ParserCreateUserQuery.cpp +++ b/src/Parsers/Access/ParserCreateUserQuery.cpp @@ -52,7 +52,6 @@ namespace bool expect_hash = false; bool expect_ldap_server_name = false; bool expect_kerberos_realm = false; - if (ParserKeyword{"WITH"}.ignore(pos, expected)) { for (auto check_type : collections::range(AuthenticationType::MAX)) @@ -67,7 +66,6 @@ namespace expect_kerberos_realm = true; else if (check_type != AuthenticationType::NO_PASSWORD) expect_password = true; - break; } } @@ -84,6 +82,16 @@ namespace type = AuthenticationType::DOUBLE_SHA1_PASSWORD; expect_hash = true; } + else if (ParserKeyword{"SHA256_HASH_SALT"}.ignore(pos, expected)) + { + type = AuthenticationType::SHA256_PASSWORD_SALT; + expect_hash = true; + } + else if (ParserKeyword{"DOUBLE_SHA1_HASH_SALT"}.ignore(pos, expected)) + { + type = AuthenticationType::DOUBLE_SHA1_PASSWORD_SALT; + expect_hash = true; + } else return false; } @@ -133,7 +141,6 @@ namespace auth_data.setLDAPServerName(value); else if (expect_kerberos_realm) auth_data.setKerberosRealm(value); - return true; }); } diff --git a/tests/queries/0_stateless/01292_create_user.reference b/tests/queries/0_stateless/01292_create_user.reference index 997a9504bb51..f3ea3172f2af 100644 --- a/tests/queries/0_stateless/01292_create_user.reference +++ b/tests/queries/0_stateless/01292_create_user.reference @@ -13,11 +13,13 @@ CREATE USER u4_01292 IDENTIFIED WITH sha256_password CREATE USER u5_01292 IDENTIFIED WITH sha256_password CREATE USER u6_01292 IDENTIFIED WITH double_sha1_password CREATE USER u7_01292 IDENTIFIED WITH double_sha1_password +CREATE USER u7_01292 IDENTIFIED WITH sha256_hash_salt CREATE USER u1_01292 IDENTIFIED WITH sha256_password CREATE USER u2_01292 IDENTIFIED WITH sha256_password CREATE USER u3_01292 IDENTIFIED WITH sha256_password CREATE USER u4_01292 IDENTIFIED WITH plaintext_password CREATE USER u5_01292 +CREATE USER u18_01292 IDENTIFIED WITH sha256_password -- host CREATE USER u1_01292 CREATE USER u2_01292 HOST NONE diff --git a/tests/queries/0_stateless/01292_create_user.sql b/tests/queries/0_stateless/01292_create_user.sql index a9582376825d..dde8c3520ff7 100644 --- a/tests/queries/0_stateless/01292_create_user.sql +++ b/tests/queries/0_stateless/01292_create_user.sql @@ -1,6 +1,6 @@ -- Tags: no-fasttest -DROP USER IF EXISTS u1_01292, u2_01292, u3_01292, u4_01292, u5_01292, u6_01292, u7_01292, u8_01292, u9_01292; +DROP USER IF EXISTS u1_01292, u2_01292, u3_01292, u4_01292, u5_01292, u6_01292, u7_01292, u8_01292, u9_01292,u18_01292; DROP USER IF EXISTS u10_01292, u11_01292, u12_01292, u13_01292, u14_01292, u15_01292, u16_01292; DROP USER IF EXISTS u2_01292_renamed; DROP USER IF EXISTS u1_01292@'%', 'u2_01292@%.myhost.com', u3_01292@'192.168.%.%', 'u4_01292@::1', u5_01292@'65:ff0c::/96'; @@ -31,6 +31,7 @@ CREATE USER u4_01292 IDENTIFIED WITH sha256_password BY 'qwe123'; CREATE USER u5_01292 IDENTIFIED WITH sha256_hash BY '18138372FAD4B94533CD4881F03DC6C69296DD897234E0CEE83F727E2E6B1F63'; CREATE USER u6_01292 IDENTIFIED WITH double_sha1_password BY 'qwe123'; CREATE USER u7_01292 IDENTIFIED WITH double_sha1_hash BY '8DCDD69CE7D121DE8013062AEAEB2A148910D50E'; +CREATE USER u18_01292 IDENTIFIED WITH sha256_hash_salt BY 'E14CB9E5C0EEEE0EA313A4E04FBD10AA17AC17AA33A3CAD4BDFE74B87CA18EF8'; SHOW CREATE USER u1_01292; SHOW CREATE USER u2_01292; SHOW CREATE USER u3_01292; @@ -43,12 +44,14 @@ ALTER USER u2_01292 IDENTIFIED BY '123qwe'; ALTER USER u3_01292 IDENTIFIED BY '123qwe'; ALTER USER u4_01292 IDENTIFIED WITH plaintext_password BY '123qwe'; ALTER USER u5_01292 NOT IDENTIFIED; +ALTER USER u18_01292 IDENTIFIED WITH sha256_password BY '123root'; SHOW CREATE USER u1_01292; SHOW CREATE USER u2_01292; SHOW CREATE USER u3_01292; SHOW CREATE USER u4_01292; SHOW CREATE USER u5_01292; -DROP USER u1_01292, u2_01292, u3_01292, u4_01292, u5_01292, u6_01292, u7_01292; +SHOW CREATE USER u18_01292; +DROP USER u1_01292, u2_01292, u3_01292, u4_01292, u5_01292, u6_01292, u7_01292, u18_01292; SELECT '-- host'; CREATE USER u1_01292 HOST ANY; From 0f8ec5f580b6816923fc492d0510a0bd1e66f828 Mon Sep 17 00:00:00 2001 From: Rajkumar Date: Mon, 4 Apr 2022 10:56:50 -0700 Subject: [PATCH 3/3] password hash salt feature --- src/Access/Common/AuthenticationData.h | 12 ++++++------ .../Access/InterpreterCreateUserQuery.cpp | 9 +++++++-- src/Parsers/Access/ASTCreateUserQuery.h | 4 ++-- tests/testflows/rbac/tests/syntax/create_user.py | 2 +- 4 files changed, 16 insertions(+), 11 deletions(-) diff --git a/src/Access/Common/AuthenticationData.h b/src/Access/Common/AuthenticationData.h index 25bd1cd98464..634d637a1941 100644 --- a/src/Access/Common/AuthenticationData.h +++ b/src/Access/Common/AuthenticationData.h @@ -21,6 +21,12 @@ enum class AuthenticationType /// This kind of hash is used by the `mysql_native_password` authentication plugin. DOUBLE_SHA1_PASSWORD, + ///Password hash with salt + SHA256_PASSWORD_SALT, + + ///Double Sha Password hash with salt + DOUBLE_SHA1_PASSWORD_SALT, + /// Password is checked by a [remote] LDAP server. Connection will be made at each authentication attempt. LDAP, @@ -28,12 +34,6 @@ enum class AuthenticationType KERBEROS, MAX, - - ///Password hash with salt - SHA256_PASSWORD_SALT, - - ///Double Sha Password hash with salt - DOUBLE_SHA1_PASSWORD_SALT, }; struct AuthenticationTypeInfo diff --git a/src/Interpreters/Access/InterpreterCreateUserQuery.cpp b/src/Interpreters/Access/InterpreterCreateUserQuery.cpp index 6650a448c800..d92e9d753887 100644 --- a/src/Interpreters/Access/InterpreterCreateUserQuery.cpp +++ b/src/Interpreters/Access/InterpreterCreateUserQuery.cpp @@ -10,7 +10,10 @@ #include #include #include - +#include +#include +#include "Common/OpenSSLHelpers.h" +#include namespace DB { @@ -40,7 +43,9 @@ namespace || query.auth_data->getType() == AuthenticationType::DOUBLE_SHA1_PASSWORD_SALT) { //generate and add salt here - String salt = "SALT123"; + pcg64_fast rng(randomSeed()); + UInt64 rand = rng(); + String salt = encodeSHA256(&rand, sizeof(rand)); user.auth_data.setSalt(salt); std::vector password = user.auth_data.getPasswordHashBinary(); std::vector salt_hash = user.auth_data.getSaltHashBinary(); diff --git a/src/Parsers/Access/ASTCreateUserQuery.h b/src/Parsers/Access/ASTCreateUserQuery.h index 92db71e85819..cc215b31b5a2 100644 --- a/src/Parsers/Access/ASTCreateUserQuery.h +++ b/src/Parsers/Access/ASTCreateUserQuery.h @@ -15,7 +15,7 @@ class ASTDatabaseOrNone; class ASTSettingsProfileElements; /** CREATE USER [IF NOT EXISTS | OR REPLACE] name - * [NOT IDENTIFIED | IDENTIFIED {[WITH {no_password|plaintext_password|sha256_password|sha256_hash|double_sha1_password|double_sha1_hash}] BY {'password'|'hash'}}|{WITH ldap SERVER 'server_name'}|{WITH kerberos [REALM 'realm']}] + * [NOT IDENTIFIED | IDENTIFIED {[WITH {no_password|plaintext_password|sha256_password|sha256_hash|double_sha1_password|double_sha1_hash|double_sha1_hash_salt|sha256_hash_salt}] BY {'password'|'hash'}}|{WITH ldap SERVER 'server_name'}|{WITH kerberos [REALM 'realm']}] * [HOST {LOCAL | NAME 'name' | REGEXP 'name_regexp' | IP 'address' | LIKE 'pattern'} [,...] | ANY | NONE] * [DEFAULT ROLE role [,...]] * [DEFAULT DATABASE database | NONE] @@ -24,7 +24,7 @@ class ASTSettingsProfileElements; * * ALTER USER [IF EXISTS] name * [RENAME TO new_name] - * [NOT IDENTIFIED | IDENTIFIED {[WITH {no_password|plaintext_password|sha256_password|sha256_hash|double_sha1_password|double_sha1_hash}] BY {'password'|'hash'}}|{WITH ldap SERVER 'server_name'}|{WITH kerberos [REALM 'realm']}] + * [NOT IDENTIFIED | IDENTIFIED {[WITH {no_password|plaintext_password|sha256_password|sha256_hash|double_sha1_password|double_sha1_hash|double_sha1_hash_salt|sha256_hash_salt}] BY {'password'|'hash'}}|{WITH ldap SERVER 'server_name'}|{WITH kerberos [REALM 'realm']}] * [[ADD|DROP] HOST {LOCAL | NAME 'name' | REGEXP 'name_regexp' | IP 'address' | LIKE 'pattern'} [,...] | ANY | NONE] * [DEFAULT ROLE role [,...] | ALL | ALL EXCEPT role [,...] ] * [DEFAULT DATABASE database | NONE] diff --git a/tests/testflows/rbac/tests/syntax/create_user.py b/tests/testflows/rbac/tests/syntax/create_user.py index 326446e4620b..ff5f174a1293 100755 --- a/tests/testflows/rbac/tests/syntax/create_user.py +++ b/tests/testflows/rbac/tests/syntax/create_user.py @@ -14,7 +14,7 @@ def feature(self, node="clickhouse1"): ```sql CREATE USER [IF NOT EXISTS | OR REPLACE] name [ON CLUSTER cluster_name] - [IDENTIFIED [WITH {NO_PASSWORD|PLAINTEXT_PASSWORD|SHA256_PASSWORD|SHA256_HASH|DOUBLE_SHA1_PASSWORD|DOUBLE_SHA1_HASH}] BY {'password'|'hash'}] + [IDENTIFIED [WITH {NO_PASSWORD|PLAINTEXT_PASSWORD|SHA256_PASSWORD|SHA256_HASH|DOUBLE_SHA1_PASSWORD|DOUBLE_SHA1_HASH|DOUBLE_SHA1_HASH_SALT|SHA256_HASH_SALT}] BY {'password'|'hash'}] [HOST {LOCAL | NAME 'name' | NAME REGEXP 'name_regexp' | IP 'address' | LIKE 'pattern'} [,...] | ANY | NONE] [DEFAULT ROLE role [,...]] [SETTINGS variable [= value] [MIN [=] min_value] [MAX [=] max_value] [READONLY|WRITABLE] | PROFILE 'profile_name'] [,...]