mirror of
https://github.com/IT4Change/gradido.git
synced 2025-12-13 07:45:54 +00:00
use new user in login
This commit is contained in:
parent
2078705a80
commit
7d826fcacd
@ -47,6 +47,9 @@ public:
|
||||
std::shared_lock<std::shared_mutex> _lock(mWorkingMutex);
|
||||
return mEncryptionKeyHash == b.getKeyHashed();
|
||||
}
|
||||
inline bool operator == (const KeyHashed& hash) const {
|
||||
return mEncryptionKeyHash == hash;
|
||||
}
|
||||
|
||||
inline bool hasKey() const { std::shared_lock<std::shared_mutex> _lock(mWorkingMutex); return mEncryptionKey != nullptr; }
|
||||
|
||||
|
||||
@ -13,7 +13,8 @@ KeyPairEd25519::KeyPairEd25519(MemoryBin* privateKey)
|
||||
{
|
||||
//memcpy(mSodiumPublic, publicKey, crypto_sign_PUBLICKEYBYTES);
|
||||
// read pubkey from private key, so we are sure it is the correct pubkey for the private key
|
||||
crypto_sign_ed25519_sk_to_pk(*privateKey, mSodiumPublic);
|
||||
|
||||
crypto_sign_ed25519_sk_to_pk(mSodiumPublic, *privateKey);
|
||||
}
|
||||
|
||||
KeyPairEd25519::KeyPairEd25519(const unsigned char* publicKey)
|
||||
@ -95,6 +96,7 @@ KeyPairEd25519* KeyPairEd25519::create(const Passphrase* passphrase)
|
||||
}
|
||||
|
||||
crypto_sign_seed_keypair(key_pair->mSodiumPublic, *key_pair->mSodiumSecret, hash);
|
||||
|
||||
return key_pair;
|
||||
|
||||
// print hex for all keys for debugging
|
||||
|
||||
@ -121,6 +121,9 @@ void LoginPage::handleRequest(Poco::Net::HTTPServerRequest& request, Poco::Net::
|
||||
}
|
||||
response.redirect(ServerConfig::g_serverPath + "/passphrase");
|
||||
return;
|
||||
case USER_KEYS_DONT_MATCH:
|
||||
addError(new Error(langCatalog->gettext("User"), langCatalog->gettext("Error in saved data, the server admin will look at it.")));
|
||||
break;
|
||||
case USER_NO_PRIVATE_KEY:
|
||||
case USER_COMPLETE:
|
||||
auto referer = request.find("Referer");
|
||||
@ -222,20 +225,20 @@ void LoginPage::handleRequest(Poco::Net::HTTPServerRequest& request, Poco::Net::
|
||||
responseStream << " <div class=\"row\">\n";
|
||||
responseStream << " <div class=\"col-12 logo-section\">\n";
|
||||
responseStream << " <a href=\"";
|
||||
#line 152 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\login.cpsp"
|
||||
#line 155 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\login.cpsp"
|
||||
responseStream << ( ServerConfig::g_php_serverPath );
|
||||
responseStream << "\" class=\"logo\">\n";
|
||||
responseStream << "\t\t\t<picture>\n";
|
||||
responseStream << "\t\t\t\t<source srcset=\"";
|
||||
#line 154 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\login.cpsp"
|
||||
#line 157 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\login.cpsp"
|
||||
responseStream << ( ServerConfig::g_php_serverPath );
|
||||
responseStream << "img/logo_schrift.webp\" type=\"image/webp\">\n";
|
||||
responseStream << "\t\t\t\t<source srcset=\"";
|
||||
#line 155 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\login.cpsp"
|
||||
#line 158 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\login.cpsp"
|
||||
responseStream << ( ServerConfig::g_php_serverPath );
|
||||
responseStream << "img/logo_schrift.png\" type=\"image/png\"> \n";
|
||||
responseStream << "\t\t\t\t<img src=\"";
|
||||
#line 156 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\login.cpsp"
|
||||
#line 159 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\login.cpsp"
|
||||
responseStream << ( ServerConfig::g_php_serverPath );
|
||||
responseStream << "img/logo_schrift.png\" alt=\"logo\" />\n";
|
||||
responseStream << "\t\t\t</picture>\n";
|
||||
@ -247,14 +250,14 @@ void LoginPage::handleRequest(Poco::Net::HTTPServerRequest& request, Poco::Net::
|
||||
responseStream << " <div class=\"grid\">\n";
|
||||
responseStream << "\t\t\t<div class=\"center-ul-container\">\n";
|
||||
responseStream << "\t\t\t\t";
|
||||
#line 165 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\login.cpsp"
|
||||
#line 168 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\login.cpsp"
|
||||
responseStream << ( getErrorsHtml() );
|
||||
responseStream << "\t \n";
|
||||
responseStream << "\t\t\t</div>\n";
|
||||
responseStream << " <div class=\"grid-body\">\n";
|
||||
responseStream << " \n";
|
||||
responseStream << "\t\t\t <!--<input type=\"hidden\" name=\"lang\" value=\"";
|
||||
#line 169 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\login.cpsp"
|
||||
#line 172 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\login.cpsp"
|
||||
responseStream << ( LanguageManager::keyForLanguage(lang) );
|
||||
responseStream << "\">-->\n";
|
||||
responseStream << "\t\t\t ";
|
||||
@ -294,46 +297,46 @@ void LoginPage::handleRequest(Poco::Net::HTTPServerRequest& request, Poco::Net::
|
||||
// end include flags.cpsp
|
||||
responseStream << "\n";
|
||||
responseStream << "\t\t\t <form action=\"";
|
||||
#line 171 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\login.cpsp"
|
||||
#line 174 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\login.cpsp"
|
||||
responseStream << ( ServerConfig::g_serverPath );
|
||||
responseStream << "/\" method=\"POST\">\n";
|
||||
responseStream << " <div class=\"row display-block\">\n";
|
||||
responseStream << " <div class=\"col-lg-7 col-md-8 col-sm-9 col-12 mx-auto form-wrapper\">\n";
|
||||
responseStream << " <div class=\"form-group input-rounded\">\n";
|
||||
responseStream << " <input type=\"text\" class=\"form-control\" name=\"login-email\" placeholder=\"";
|
||||
#line 175 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\login.cpsp"
|
||||
#line 178 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\login.cpsp"
|
||||
responseStream << ( langCatalog->gettext("E-Mail") );
|
||||
responseStream << "\" value=\"";
|
||||
#line 175 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\login.cpsp"
|
||||
#line 178 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\login.cpsp"
|
||||
responseStream << ( presetEmail );
|
||||
responseStream << "\"/>\n";
|
||||
responseStream << " </div>\n";
|
||||
responseStream << " <div class=\"form-group input-rounded\">\n";
|
||||
responseStream << " <input type=\"password\" class=\"form-control\" name=\"login-password\" placeholder=\"";
|
||||
#line 178 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\login.cpsp"
|
||||
#line 181 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\login.cpsp"
|
||||
responseStream << ( langCatalog->gettext("Password") );
|
||||
responseStream << "\" />\n";
|
||||
responseStream << " </div>\n";
|
||||
responseStream << " <button type=\"submit\" name=\"submit\" class=\"btn btn-primary btn-block\">";
|
||||
#line 180 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\login.cpsp"
|
||||
#line 183 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\login.cpsp"
|
||||
responseStream << ( langCatalog->gettext(" Login ") );
|
||||
responseStream << "</button>\n";
|
||||
responseStream << " <div class=\"signup-link\">\n";
|
||||
responseStream << " <p>";
|
||||
#line 182 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\login.cpsp"
|
||||
#line 185 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\login.cpsp"
|
||||
responseStream << ( langCatalog->gettext("You haven't any account yet? Please follow the link to create one.") );
|
||||
responseStream << "</p>\n";
|
||||
responseStream << " <a href=\"https://gradido.com\">";
|
||||
#line 183 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\login.cpsp"
|
||||
#line 186 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\login.cpsp"
|
||||
responseStream << ( langCatalog->gettext("Create New Account") );
|
||||
responseStream << "</a>\n";
|
||||
responseStream << " </div>\n";
|
||||
responseStream << "\t\t\t\t\t<div class=\"reset-pwd-link\">\n";
|
||||
responseStream << "\t\t\t\t\t\t<a href=\"";
|
||||
#line 186 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\login.cpsp"
|
||||
#line 189 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\login.cpsp"
|
||||
responseStream << ( ServerConfig::g_serverPath );
|
||||
responseStream << "/resetPassword\">";
|
||||
#line 186 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\login.cpsp"
|
||||
#line 189 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\login.cpsp"
|
||||
responseStream << ( langCatalog->gettext("Passwort vergessen") );
|
||||
responseStream << "</a>\n";
|
||||
responseStream << "\t\t\t\t\t</div>\n";
|
||||
|
||||
@ -122,6 +122,42 @@ namespace controller {
|
||||
return json;
|
||||
}
|
||||
|
||||
int User::login(const std::string& password)
|
||||
{
|
||||
if (mPassword && mPassword->hasKey()) {
|
||||
return 2;
|
||||
}
|
||||
std::unique_lock<std::shared_mutex> _lock(mSharedMutex);
|
||||
auto authenticated_encryption = new AuthenticatedEncryption();
|
||||
auto model = getModel();
|
||||
assert(authenticated_encryption && model);
|
||||
|
||||
authenticated_encryption->createKey(model->getEmail(), password);
|
||||
if (authenticated_encryption->getKeyHashed() == model->getPasswordHashed()) {
|
||||
MemoryBin* clear_private_key = nullptr;
|
||||
auto priv_key_encrypted = model->getPrivateKeyEncrypted();
|
||||
auto priv_key_bin = MemoryManager::getInstance()->getFreeMemory(priv_key_encrypted.size());
|
||||
memcpy(*priv_key_bin, priv_key_encrypted.data(), priv_key_encrypted.size());
|
||||
if (AuthenticatedEncryption::AUTH_DECRYPT_OK == authenticated_encryption->decrypt(priv_key_bin, &clear_private_key)) {
|
||||
auto gradido_key_pair = new KeyPairEd25519(clear_private_key);
|
||||
if (*gradido_key_pair != model->getPublicKey()) {
|
||||
delete authenticated_encryption;
|
||||
delete gradido_key_pair;
|
||||
return -1;
|
||||
}
|
||||
if (mGradidoKeyPair) delete mGradidoKeyPair;
|
||||
mGradidoKeyPair = gradido_key_pair;
|
||||
if (mPassword) delete mPassword;
|
||||
mPassword = authenticated_encryption;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
delete authenticated_encryption;
|
||||
|
||||
// password didn't match
|
||||
return 0;
|
||||
}
|
||||
|
||||
int User::setPassword(AuthenticatedEncryption* passwd)
|
||||
{
|
||||
std::unique_lock<std::shared_mutex> _lock(mSharedMutex);
|
||||
@ -130,7 +166,14 @@ namespace controller {
|
||||
|
||||
if (mPassword)
|
||||
{
|
||||
if (mPassword == passwd) return 0;
|
||||
// if keys matched
|
||||
if (*mPassword == *passwd) {
|
||||
// but separate objects
|
||||
if (mPassword != passwd) {
|
||||
delete passwd;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
// if password exist but gradido key pair not, try to load key pair
|
||||
if ((!mGradidoKeyPair || !mGradidoKeyPair->hasPrivateKey()) && model->hasPrivateKeyEncrypted()) {
|
||||
//if (!mGradidoKeyPair) mGradidoKeyPair = new KeyPairEd25519;
|
||||
@ -143,24 +186,33 @@ namespace controller {
|
||||
if (*mGradidoKeyPair != model->getPublicKey()) {
|
||||
delete mGradidoKeyPair;
|
||||
mGradidoKeyPair = nullptr;
|
||||
delete passwd;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delete passwd;
|
||||
}
|
||||
// replace old password with new
|
||||
if (mPassword && mPassword != passwd) {
|
||||
delete mPassword;
|
||||
}
|
||||
mPassword = passwd;
|
||||
|
||||
// set new encrypted password and hash
|
||||
model->setPasswordHashed(mPassword->getKeyHashed());
|
||||
auto encryptedPrivateKey = mGradidoKeyPair->getCryptedPrivKey(mPassword);
|
||||
model->setPrivateKey(encryptedPrivateKey);
|
||||
MemoryManager::getInstance()->releaseMemory(encryptedPrivateKey);
|
||||
int result = 2;
|
||||
if (mGradidoKeyPair && mGradidoKeyPair->hasPrivateKey()) {
|
||||
auto encryptedPrivateKey = mGradidoKeyPair->getCryptedPrivKey(mPassword);
|
||||
model->setPrivateKey(encryptedPrivateKey);
|
||||
MemoryManager::getInstance()->releaseMemory(encryptedPrivateKey);
|
||||
|
||||
result = model->updatePrivkeyAndPasswordHash();
|
||||
}
|
||||
else {
|
||||
model->updateIntoDB("password", mPassword->getKeyHashed());
|
||||
}
|
||||
// save changes to db
|
||||
return model->updatePrivkeyAndPasswordHash();
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
@ -40,13 +40,23 @@ namespace controller {
|
||||
std::string getEmailWithNames();
|
||||
const std::string& getPublicHex();
|
||||
|
||||
//! \brief check if password match saved password, long duration
|
||||
//! \return 1 logged in
|
||||
//! \return 2 already logged in
|
||||
//! \return 0 password didn't match
|
||||
//! \return -1 error saved public key didn't match with private key
|
||||
//! - create authenticated encryption key from password and email
|
||||
//! - compare hash with in db saved hash
|
||||
|
||||
int login(const std::string& password);
|
||||
|
||||
// ***********************************************************************************
|
||||
// password related
|
||||
//! \brief set authenticated encryption and save hash in db, should also re encrypt private key if exist
|
||||
//! \brief set authenticated encryption and save hash in db, also re encrypt private key if exist
|
||||
//! \param passwd take owner ship
|
||||
//! \return 0 = new and current passwords are the same
|
||||
//! \return 1 = password changed, private key re-encrypted and saved into db
|
||||
//! \return 2 = password changed, only hash stored in db, couldn't load private key for re-encryption
|
||||
//! \return -1 = stored pubkey and private key didn't match
|
||||
int setPassword(AuthenticatedEncryption* passwd);
|
||||
|
||||
@ -54,8 +64,14 @@ namespace controller {
|
||||
std::shared_lock<std::shared_mutex> _lock(mSharedMutex);
|
||||
return mPassword;
|
||||
}
|
||||
inline const KeyPairEd25519* getGradidoKeyPair() {
|
||||
std::shared_lock<std::shared_mutex> _lock(mSharedMutex);
|
||||
return mGradidoKeyPair;
|
||||
}
|
||||
protected:
|
||||
User(model::table::User* dbModel);
|
||||
|
||||
|
||||
|
||||
std::string mPublicHex;
|
||||
|
||||
|
||||
@ -631,6 +631,7 @@ bool Session::isPwdValid(const std::string& pwd)
|
||||
|
||||
UserStates Session::loadUser(const std::string& email, const std::string& password)
|
||||
{
|
||||
static const char* functionName = "Session::loadUser";
|
||||
auto observer = SingletonTaskObserver::getInstance();
|
||||
if (email != "") {
|
||||
if (observer->getTaskCount(email, TASK_OBSERVER_PASSWORD_CREATION) > 0) {
|
||||
@ -638,7 +639,7 @@ UserStates Session::loadUser(const std::string& email, const std::string& passwo
|
||||
}
|
||||
}
|
||||
//Profiler usedTime;
|
||||
lock("Session::loadUser");
|
||||
lock(functionName);
|
||||
if (mSessionUser && mSessionUser->getEmail() != email) {
|
||||
mSessionUser.assign(nullptr);
|
||||
mNewUser.assign(nullptr);
|
||||
@ -653,6 +654,20 @@ UserStates Session::loadUser(const std::string& email, const std::string& passwo
|
||||
//mSessionUser = new User(email.data());
|
||||
}
|
||||
if (mSessionUser->getUserState() >= USER_LOADED_FROM_DB) {
|
||||
int loginResult = mNewUser->login(password);
|
||||
|
||||
if (-1 == loginResult) {
|
||||
addError(new Error(functionName, "error in user data set, saved pubkey didn't match extracted pubkey from private key"));
|
||||
addError(new ParamError(functionName, "user email", mNewUser->getModel()->getEmail()));
|
||||
sendErrorsAsEmail();
|
||||
//unlock();
|
||||
//return USER_KEYS_DONT_MATCH;
|
||||
}
|
||||
if (0 == loginResult) {
|
||||
unlock();
|
||||
return USER_PASSWORD_INCORRECT;
|
||||
}
|
||||
// can be removed if session user isn't used any more
|
||||
if (mNewUser->getModel()->getPasswordHashed() && !mSessionUser->validatePwd(password, this)) {
|
||||
unlock();
|
||||
return USER_PASSWORD_INCORRECT;
|
||||
|
||||
@ -35,6 +35,7 @@ enum UserStates
|
||||
USER_EMAIL_NOT_ACTIVATED,
|
||||
USER_NO_KEYS,
|
||||
USER_NO_PRIVATE_KEY,
|
||||
USER_KEYS_DONT_MATCH,
|
||||
USER_COMPLETE
|
||||
};
|
||||
|
||||
|
||||
@ -0,0 +1,10 @@
|
||||
#include "TestUser.h"
|
||||
|
||||
namespace controller {
|
||||
void TestUser::SetUp()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//TEST_F(TestUser, )
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
#ifndef __GRADIDO_LOGIN_SERVER_TEST_CONTROLLER_USER_H
|
||||
#define __GRADIDO_LOGIN_SERVER_TEST_CONTROLLER_USER_H
|
||||
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
namespace controller {
|
||||
|
||||
class TestUser : public ::testing::Test {
|
||||
protected:
|
||||
void SetUp() override;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#endif //__GRADIDO_LOGIN_SERVER_TEST_CONTROLLER_USER_H
|
||||
@ -4,7 +4,9 @@
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "Poco/Util/PropertyFileConfiguration.h"
|
||||
#include "Poco/Environment.h"
|
||||
|
||||
#include "../SingletonManager/ConnectionManager.h"
|
||||
|
||||
|
||||
std::list<Test*> gTests;
|
||||
@ -35,6 +37,24 @@ int load() {
|
||||
return -2;
|
||||
}
|
||||
|
||||
// start cpu scheduler
|
||||
uint8_t worker_count = Poco::Environment::processorCount();
|
||||
|
||||
ServerConfig::g_CPUScheduler = new UniLib::controller::CPUSheduler(worker_count, "Default Worker");
|
||||
ServerConfig::g_CryptoCPUScheduler = new UniLib::controller::CPUSheduler(2, "Crypto Worker");
|
||||
|
||||
// load up connection configs
|
||||
// register MySQL connector
|
||||
Poco::Data::MySQL::Connector::registerConnector();
|
||||
//Poco::Data::MySQL::Connector::KEY;
|
||||
auto conn = ConnectionManager::getInstance();
|
||||
//conn->setConnection()
|
||||
//printf("try connect login server mysql db\n");
|
||||
conn->setConnectionsFromConfig(*test_config, CONNECTION_MYSQL_LOGIN_SERVER);
|
||||
//printf("try connect php server mysql \n");
|
||||
conn->setConnectionsFromConfig(*test_config, CONNECTION_MYSQL_PHP_SERVER);
|
||||
|
||||
|
||||
fillTests();
|
||||
for (std::list<Test*>::iterator it = gTests.begin(); it != gTests.end(); it++)
|
||||
{
|
||||
|
||||
@ -100,6 +100,9 @@
|
||||
}
|
||||
response.redirect(ServerConfig::g_serverPath + "/passphrase");
|
||||
return;
|
||||
case USER_KEYS_DONT_MATCH:
|
||||
addError(new Error(langCatalog->gettext("User"), langCatalog->gettext("Error in saved data, the server admin will look at it.")));
|
||||
break;
|
||||
case USER_NO_PRIVATE_KEY:
|
||||
case USER_COMPLETE:
|
||||
auto referer = request.find("Referer");
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user