mirror of https://github.com/Icinga/icinga2.git
Move new password functions into tlsutility
This commit is contained in:
parent
92e2faaa08
commit
65a806f5dc
|
@ -810,4 +810,28 @@ std::string to_string(const errinfo_openssl_error& e)
|
||||||
return "[errinfo_openssl_error]" + tmp.str() + "\n";
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,6 +56,8 @@ String SHA1(const String& s, bool binary = false);
|
||||||
String SHA256(const String& s);
|
String SHA256(const String& s);
|
||||||
String RandomString(int length);
|
String RandomString(int length);
|
||||||
bool VerifyCertificate(const std::shared_ptr<X509>& caCertificate, const std::shared_ptr<X509>& certificate);
|
bool VerifyCertificate(const std::shared_ptr<X509>& caCertificate, const std::shared_ptr<X509>& 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 { };
|
class openssl_error : virtual public std::exception, virtual public boost::exception { };
|
||||||
|
|
||||||
|
|
|
@ -68,7 +68,7 @@ int ApiUserCommand::Run(const boost::program_options::variables_map& vm, const s
|
||||||
String passwd = vm["passwd"].as<std::string>();
|
String passwd = vm["passwd"].as<std::string>();
|
||||||
String salt = vm.count("salt") ? String(vm["salt"].as<std::string>()) : RandomString(8);
|
String salt = vm.count("salt") ? String(vm["salt"].as<std::string>()) : RandomString(8);
|
||||||
|
|
||||||
String hashedPassword = ApiUser::CreateHashedPasswordString(passwd, salt, true);
|
String hashedPassword = HashPassword(passwd, salt, true);
|
||||||
|
|
||||||
std::cout
|
std::cout
|
||||||
<< "object ApiUser \"" << user << "\" {\n"
|
<< "object ApiUser \"" << user << "\" {\n"
|
||||||
|
|
|
@ -31,7 +31,7 @@ void ApiUser::OnConfigLoaded(void)
|
||||||
ObjectImpl<ApiUser>::OnConfigLoaded();
|
ObjectImpl<ApiUser>::OnConfigLoaded();
|
||||||
|
|
||||||
if (this->GetPasswordHash().IsEmpty())
|
if (this->GetPasswordHash().IsEmpty())
|
||||||
SetPasswordHash(CreateHashedPasswordString(GetPassword(), RandomString(8), true));
|
SetPasswordHash(HashPassword(GetPassword(), RandomString(8), true));
|
||||||
}
|
}
|
||||||
|
|
||||||
ApiUser::Ptr ApiUser::GetByClientCN(const String& cn)
|
ApiUser::Ptr ApiUser::GetByClientCN(const String& cn)
|
||||||
|
@ -44,23 +44,6 @@ ApiUser::Ptr ApiUser::GetByClientCN(const String& cn)
|
||||||
return nullptr;
|
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
|
Dictionary::Ptr ApiUser::GetPasswordDict(void) const
|
||||||
{
|
{
|
||||||
String password = this->GetPasswordHash();
|
String password = this->GetPasswordHash();
|
||||||
|
@ -80,13 +63,3 @@ Dictionary::Ptr ApiUser::GetPasswordDict(void) const
|
||||||
|
|
||||||
return passwordDict;
|
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);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
@ -38,10 +38,8 @@ public:
|
||||||
virtual void OnConfigLoaded(void) override;
|
virtual void OnConfigLoaded(void) override;
|
||||||
|
|
||||||
static ApiUser::Ptr GetByClientCN(const String& cn);
|
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;
|
Dictionary::Ptr GetPasswordDict(void) const;
|
||||||
bool ComparePassword(String password) const;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
#include "base/objectlock.hpp"
|
#include "base/objectlock.hpp"
|
||||||
#include "base/utility.hpp"
|
#include "base/utility.hpp"
|
||||||
#include "base/logger.hpp"
|
#include "base/logger.hpp"
|
||||||
|
#include "base/tlsutility.hpp"
|
||||||
#include "base/exception.hpp"
|
#include "base/exception.hpp"
|
||||||
#include "base/convert.hpp"
|
#include "base/convert.hpp"
|
||||||
#include <boost/thread/once.hpp>
|
#include <boost/thread/once.hpp>
|
||||||
|
@ -157,8 +158,13 @@ void HttpServerConnection::ProcessMessageAsync(HttpRequest& request)
|
||||||
user = ApiUser::GetByName(username);
|
user = ApiUser::GetByName(username);
|
||||||
|
|
||||||
/* Deny authentication if 1) given password is empty 2) configured password does not match. */
|
/* 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();
|
user.reset();
|
||||||
|
else {
|
||||||
|
Dictionary::Ptr passwordDict = user->GetPasswordDict();
|
||||||
|
if (!ComparePassword(passwordDict->Get("password"), password, passwordDict->Get("salt")))
|
||||||
|
user.reset();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String requestUrl = request.RequestUrl->Format();
|
String requestUrl = request.RequestUrl->Format();
|
||||||
|
|
|
@ -36,7 +36,7 @@ BOOST_AUTO_TEST_CASE(password)
|
||||||
String passwd = RandomString(16);
|
String passwd = RandomString(16);
|
||||||
String salt = RandomString(8);
|
String salt = RandomString(8);
|
||||||
user->SetPassword("ThisShouldBeIgnored");
|
user->SetPassword("ThisShouldBeIgnored");
|
||||||
user->SetPasswordHash(ApiUser::CreateHashedPasswordString(passwd, salt, true));
|
user->SetPasswordHash(HashPassword(passwd, salt, true));
|
||||||
|
|
||||||
BOOST_CHECK(user->GetPasswordHash() != passwd);
|
BOOST_CHECK(user->GetPasswordHash() != passwd);
|
||||||
|
|
||||||
|
@ -44,8 +44,8 @@ BOOST_AUTO_TEST_CASE(password)
|
||||||
|
|
||||||
BOOST_CHECK(passwdd);
|
BOOST_CHECK(passwdd);
|
||||||
BOOST_CHECK(passwdd->Get("salt") == salt);
|
BOOST_CHECK(passwdd->Get("salt") == salt);
|
||||||
BOOST_CHECK(user->ComparePassword(passwd));
|
BOOST_CHECK(ComparePassword(passwdd->Get("password"), passwd, salt));
|
||||||
BOOST_CHECK(!user->ComparePassword("wrong password uwu!"));
|
BOOST_CHECK(!ComparePassword(passwdd->Get("password"), "wrong password uwu!", salt));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue