From 65a806f5dc872786661aadb4b910601e2c4f9364 Mon Sep 17 00:00:00 2001 From: Jean Flach Date: Fri, 22 Dec 2017 12:14:31 +0100 Subject: [PATCH] Move new password functions into tlsutility --- lib/base/tlsutility.cpp | 24 ++++++++++++++++++++++++ lib/base/tlsutility.hpp | 2 ++ lib/cli/apiusercommand.cpp | 2 +- lib/remote/apiuser.cpp | 29 +---------------------------- lib/remote/apiuser.hpp | 2 -- lib/remote/httpserverconnection.cpp | 8 +++++++- test/remote-user.cpp | 6 +++--- 7 files changed, 38 insertions(+), 35 deletions(-) diff --git a/lib/base/tlsutility.cpp b/lib/base/tlsutility.cpp index 1f74a2735..cb7a76f57 100644 --- a/lib/base/tlsutility.cpp +++ b/lib/base/tlsutility.cpp @@ -810,4 +810,28 @@ std::string to_string(const errinfo_openssl_error& e) return "[errinfo_openssl_error]" + tmp.str() + "\n"; } +bool ComparePassword(const String hash, const String password, const String salt) +{ + String otherHash = HashPassword(password, salt); + + const char *p1 = otherHash.CStr(); + const char *p2 = hash.CStr(); + + volatile char c = 0; + + for (size_t i=0; i<64; ++i) + c |= p1[i] ^ p2[i]; + + return (c == 0); +} + +String HashPassword(const String& password, const String& salt, const bool shadow) +{ + if (shadow) + //Using /etc/shadow password format. The 5 means SHA256 is being used + return String("$5$" + salt + "$" + PBKDF2_SHA256(password, salt, 1000)); + else + return PBKDF2_SHA256(password, salt, 1000); +} + } diff --git a/lib/base/tlsutility.hpp b/lib/base/tlsutility.hpp index 38df7e587..3d7b29dbd 100644 --- a/lib/base/tlsutility.hpp +++ b/lib/base/tlsutility.hpp @@ -56,6 +56,8 @@ String SHA1(const String& s, bool binary = false); String SHA256(const String& s); String RandomString(int length); bool VerifyCertificate(const std::shared_ptr& caCertificate, const std::shared_ptr& certificate); +bool ComparePassword(const String hash, const String password, const String Salt); +String HashPassword(const String& password, const String& salt, const bool shadow = false); class openssl_error : virtual public std::exception, virtual public boost::exception { }; diff --git a/lib/cli/apiusercommand.cpp b/lib/cli/apiusercommand.cpp index 9d43e120f..1cd5b4858 100644 --- a/lib/cli/apiusercommand.cpp +++ b/lib/cli/apiusercommand.cpp @@ -68,7 +68,7 @@ int ApiUserCommand::Run(const boost::program_options::variables_map& vm, const s String passwd = vm["passwd"].as(); String salt = vm.count("salt") ? String(vm["salt"].as()) : RandomString(8); - String hashedPassword = ApiUser::CreateHashedPasswordString(passwd, salt, true); + String hashedPassword = HashPassword(passwd, salt, true); std::cout << "object ApiUser \"" << user << "\" {\n" diff --git a/lib/remote/apiuser.cpp b/lib/remote/apiuser.cpp index ea3eb7849..0e92f9149 100644 --- a/lib/remote/apiuser.cpp +++ b/lib/remote/apiuser.cpp @@ -31,7 +31,7 @@ void ApiUser::OnConfigLoaded(void) ObjectImpl::OnConfigLoaded(); if (this->GetPasswordHash().IsEmpty()) - SetPasswordHash(CreateHashedPasswordString(GetPassword(), RandomString(8), true)); + SetPasswordHash(HashPassword(GetPassword(), RandomString(8), true)); } ApiUser::Ptr ApiUser::GetByClientCN(const String& cn) @@ -44,23 +44,6 @@ ApiUser::Ptr ApiUser::GetByClientCN(const String& cn) return nullptr; } -bool ApiUser::ComparePassword(String password) const -{ - Dictionary::Ptr passwordDict = this->GetPasswordDict(); - String thisPassword = passwordDict->Get("password"); - String otherPassword = CreateHashedPasswordString(password, passwordDict->Get("salt"), false); - - const char *p1 = otherPassword.CStr(); - const char *p2 = thisPassword.CStr(); - - volatile char c = 0; - - for (size_t i=0; i<64; ++i) - c |= p1[i] ^ p2[i]; - - return (c == 0); -} - Dictionary::Ptr ApiUser::GetPasswordDict(void) const { String password = this->GetPasswordHash(); @@ -80,13 +63,3 @@ Dictionary::Ptr ApiUser::GetPasswordDict(void) const return passwordDict; } - -String ApiUser::CreateHashedPasswordString(const String& password, const String& salt, const bool shadow) -{ - if (shadow) - //Using /etc/shadow password format. The 5 means SHA256 is being used - return String("$5$" + salt + "$" + PBKDF2_SHA256(password, salt, 1000)); - else - return PBKDF2_SHA256(password, salt, 1000); - -} diff --git a/lib/remote/apiuser.hpp b/lib/remote/apiuser.hpp index eeae3c77b..4e3f673f2 100644 --- a/lib/remote/apiuser.hpp +++ b/lib/remote/apiuser.hpp @@ -38,10 +38,8 @@ public: virtual void OnConfigLoaded(void) override; static ApiUser::Ptr GetByClientCN(const String& cn); - static String CreateHashedPasswordString(const String& password, const String& salt, const bool shadow = false); Dictionary::Ptr GetPasswordDict(void) const; - bool ComparePassword(String password) const; }; } diff --git a/lib/remote/httpserverconnection.cpp b/lib/remote/httpserverconnection.cpp index 4fbd774b7..8962258e3 100644 --- a/lib/remote/httpserverconnection.cpp +++ b/lib/remote/httpserverconnection.cpp @@ -28,6 +28,7 @@ #include "base/objectlock.hpp" #include "base/utility.hpp" #include "base/logger.hpp" +#include "base/tlsutility.hpp" #include "base/exception.hpp" #include "base/convert.hpp" #include @@ -157,8 +158,13 @@ void HttpServerConnection::ProcessMessageAsync(HttpRequest& request) user = ApiUser::GetByName(username); /* Deny authentication if 1) given password is empty 2) configured password does not match. */ - if (password.IsEmpty() || !user || !user->ComparePassword(password)) + if (!user || password.IsEmpty()) user.reset(); + else { + Dictionary::Ptr passwordDict = user->GetPasswordDict(); + if (!ComparePassword(passwordDict->Get("password"), password, passwordDict->Get("salt"))) + user.reset(); + } } String requestUrl = request.RequestUrl->Format(); diff --git a/test/remote-user.cpp b/test/remote-user.cpp index eafa0e721..1c327bacb 100644 --- a/test/remote-user.cpp +++ b/test/remote-user.cpp @@ -36,7 +36,7 @@ BOOST_AUTO_TEST_CASE(password) String passwd = RandomString(16); String salt = RandomString(8); user->SetPassword("ThisShouldBeIgnored"); - user->SetPasswordHash(ApiUser::CreateHashedPasswordString(passwd, salt, true)); + user->SetPasswordHash(HashPassword(passwd, salt, true)); BOOST_CHECK(user->GetPasswordHash() != passwd); @@ -44,8 +44,8 @@ BOOST_AUTO_TEST_CASE(password) BOOST_CHECK(passwdd); BOOST_CHECK(passwdd->Get("salt") == salt); - BOOST_CHECK(user->ComparePassword(passwd)); - BOOST_CHECK(!user->ComparePassword("wrong password uwu!")); + BOOST_CHECK(ComparePassword(passwdd->Get("password"), passwd, salt)); + BOOST_CHECK(!ComparePassword(passwdd->Get("password"), "wrong password uwu!", salt)); #endif } -- 2.40.0