mirror of
https://github.com/IT4Change/gradido.git
synced 2025-12-13 07:45:54 +00:00
use controller::User for login in Session, for direct register without showing passphrase direct and using new KeyPairEd25519, AuthenticatedEncryption and Passphrase classes
This commit is contained in:
parent
9f010cc5df
commit
30ba3d7f78
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#include "../SingletonManager/SessionManager.h"
|
#include "../SingletonManager/SessionManager.h"
|
||||||
#include "../SingletonManager/ErrorManager.h"
|
#include "../SingletonManager/ErrorManager.h"
|
||||||
|
#include "../SingletonManager/SingletonTaskObserver.h"
|
||||||
|
|
||||||
#include "../lib/DataTypeConverter.h"
|
#include "../lib/DataTypeConverter.h"
|
||||||
|
|
||||||
@ -15,7 +16,7 @@
|
|||||||
|
|
||||||
namespace controller {
|
namespace controller {
|
||||||
User::User(model::table::User* dbModel)
|
User::User(model::table::User* dbModel)
|
||||||
: mPassword(nullptr), mGradidoKeyPair(nullptr)
|
: mPassword(nullptr), mGradidoKeyPair(nullptr), mCanDecryptPrivateKey(false)
|
||||||
{
|
{
|
||||||
mDBModel = dbModel;
|
mDBModel = dbModel;
|
||||||
}
|
}
|
||||||
@ -130,15 +131,23 @@ namespace controller {
|
|||||||
if (!mPassword.isNull() && mPassword->hasKey()) {
|
if (!mPassword.isNull() && mPassword->hasKey()) {
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
auto observer = SingletonTaskObserver::getInstance();
|
||||||
|
|
||||||
std::unique_lock<std::shared_mutex> _lock(mSharedMutex);
|
std::unique_lock<std::shared_mutex> _lock(mSharedMutex);
|
||||||
assert(mPassword.isNull());
|
assert(mPassword.isNull());
|
||||||
|
|
||||||
Poco::AutoPtr<AuthenticatedEncryption> authenticated_encryption(new AuthenticatedEncryption);
|
|
||||||
auto model = getModel();
|
auto model = getModel();
|
||||||
|
auto email_hash = observer->makeHash(model->getEmail());
|
||||||
|
if (observer->getTaskCount(email_hash, TASK_OBSERVER_PASSWORD_CREATION) > 0) {
|
||||||
|
return -3;
|
||||||
|
}
|
||||||
|
observer->addTask(email_hash, TASK_OBSERVER_PASSWORD_CREATION);
|
||||||
|
Poco::AutoPtr<AuthenticatedEncryption> authenticated_encryption(new AuthenticatedEncryption);
|
||||||
assert(!authenticated_encryption.isNull() && model);
|
assert(!authenticated_encryption.isNull() && model);
|
||||||
|
|
||||||
authenticated_encryption->createKey(model->getEmail(), password);
|
authenticated_encryption->createKey(model->getEmail(), password);
|
||||||
|
|
||||||
|
observer->removeTask(email_hash, TASK_OBSERVER_PASSWORD_CREATION);
|
||||||
|
|
||||||
if (authenticated_encryption->getKeyHashed() == model->getPasswordHashed())
|
if (authenticated_encryption->getKeyHashed() == model->getPasswordHashed())
|
||||||
{
|
{
|
||||||
// printf("[User::login] password key hashed is the same as saved password hash\n");
|
// printf("[User::login] password key hashed is the same as saved password hash\n");
|
||||||
@ -155,6 +164,7 @@ namespace controller {
|
|||||||
if (mGradidoKeyPair) {
|
if (mGradidoKeyPair) {
|
||||||
if (mGradidoKeyPair->isTheSame(clear_private_key) == 0) {
|
if (mGradidoKeyPair->isTheSame(clear_private_key) == 0) {
|
||||||
mPassword = authenticated_encryption;
|
mPassword = authenticated_encryption;
|
||||||
|
mCanDecryptPrivateKey = true;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -171,6 +181,7 @@ namespace controller {
|
|||||||
}
|
}
|
||||||
//printf("correct pwd\n");
|
//printf("correct pwd\n");
|
||||||
mPassword = authenticated_encryption;
|
mPassword = authenticated_encryption;
|
||||||
|
mCanDecryptPrivateKey = true;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -193,16 +204,30 @@ namespace controller {
|
|||||||
std::unique_lock<std::shared_mutex> _lock(mSharedMutex);
|
std::unique_lock<std::shared_mutex> _lock(mSharedMutex);
|
||||||
if (mGradidoKeyPair) delete mGradidoKeyPair;
|
if (mGradidoKeyPair) delete mGradidoKeyPair;
|
||||||
mGradidoKeyPair = gradidoKeyPair;
|
mGradidoKeyPair = gradidoKeyPair;
|
||||||
getModel()->setPublicKey(mGradidoKeyPair->getPublicKey());
|
|
||||||
if (mPassword && mPassword->hasKey()) {
|
|
||||||
auto model = getModel();
|
auto model = getModel();
|
||||||
|
model->setPublicKey(mGradidoKeyPair->getPublicKey());
|
||||||
|
if (mPassword && mPassword->hasKey()) {
|
||||||
model->setPrivateKey(mGradidoKeyPair->getCryptedPrivKey(mPassword));
|
model->setPrivateKey(mGradidoKeyPair->getCryptedPrivKey(mPassword));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
int User::setNewPassword(const std::string& password)
|
||||||
|
{
|
||||||
|
auto observer = SingletonTaskObserver::getInstance();
|
||||||
|
auto model = getModel();
|
||||||
|
auto email_hash = observer->makeHash(model->getEmail());
|
||||||
|
|
||||||
int User::setPassword(Poco::AutoPtr<AuthenticatedEncryption> passwd)
|
observer->addTask(email_hash, TASK_OBSERVER_PASSWORD_CREATION);
|
||||||
|
Poco::AutoPtr<AuthenticatedEncryption> authenticated_encryption(new AuthenticatedEncryption);
|
||||||
|
assert(!authenticated_encryption.isNull() && model);
|
||||||
|
authenticated_encryption->createKey(model->getEmail(), password);
|
||||||
|
|
||||||
|
observer->removeTask(email_hash, TASK_OBSERVER_PASSWORD_CREATION);
|
||||||
|
return setNewPassword(authenticated_encryption);
|
||||||
|
}
|
||||||
|
|
||||||
|
int User::setNewPassword(Poco::AutoPtr<AuthenticatedEncryption> passwd)
|
||||||
{
|
{
|
||||||
std::unique_lock<std::shared_mutex> _lock(mSharedMutex);
|
std::unique_lock<std::shared_mutex> _lock(mSharedMutex);
|
||||||
auto model = getModel();
|
auto model = getModel();
|
||||||
@ -232,6 +257,7 @@ namespace controller {
|
|||||||
if (*mGradidoKeyPair != model->getPublicKey()) {
|
if (*mGradidoKeyPair != model->getPublicKey()) {
|
||||||
delete mGradidoKeyPair;
|
delete mGradidoKeyPair;
|
||||||
mGradidoKeyPair = nullptr;
|
mGradidoKeyPair = nullptr;
|
||||||
|
mCanDecryptPrivateKey = false;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -249,6 +275,7 @@ namespace controller {
|
|||||||
MemoryManager::getInstance()->releaseMemory(encryptedPrivateKey);
|
MemoryManager::getInstance()->releaseMemory(encryptedPrivateKey);
|
||||||
|
|
||||||
result = model->updatePrivkeyAndPasswordHash();
|
result = model->updatePrivkeyAndPasswordHash();
|
||||||
|
mCanDecryptPrivateKey = true;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
model->updateIntoDB("password", mPassword->getKeyHashed());
|
model->updateIntoDB("password", mPassword->getKeyHashed());
|
||||||
|
|||||||
@ -50,12 +50,13 @@ namespace controller {
|
|||||||
std::string getEmailWithNames();
|
std::string getEmailWithNames();
|
||||||
const std::string& getPublicHex();
|
const std::string& getPublicHex();
|
||||||
|
|
||||||
//! \brief check if password match saved password, long duration
|
//! \brief check if password match saved password, long duration, load Key pair
|
||||||
//! \return 1 logged in
|
//! \return 1 logged in
|
||||||
//! \return 2 already logged in
|
//! \return 2 already logged in
|
||||||
//! \return 0 password didn't match
|
//! \return 0 password didn't match
|
||||||
//! \return -1 error saved public key didn't match with private key
|
//! \return -1 error saved public key didn't match with private key
|
||||||
//! \return -2 error decrypting private key
|
//! \return -2 error decrypting private key
|
||||||
|
//! \return -3 password key creation already running
|
||||||
//! - create authenticated encryption key from password and email
|
//! - create authenticated encryption key from password and email
|
||||||
//! - compare hash with in db saved hash
|
//! - compare hash with in db saved hash
|
||||||
|
|
||||||
@ -69,7 +70,16 @@ namespace controller {
|
|||||||
//! \return 1 = password changed, private key re-encrypted and saved into db
|
//! \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 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
|
//! \return -1 = stored pubkey and private key didn't match
|
||||||
int setPassword(Poco::AutoPtr<AuthenticatedEncryption> passwd);
|
int setNewPassword(Poco::AutoPtr<AuthenticatedEncryption> passwd);
|
||||||
|
|
||||||
|
|
||||||
|
//! \brief set authenticated encryption and save hash in db, also re encrypt private key if exist
|
||||||
|
//! \param password as string
|
||||||
|
//! \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 setNewPassword(const std::string& password);
|
||||||
|
|
||||||
//! \brief return AuthenticatedEncryption Auto Pointer
|
//! \brief return AuthenticatedEncryption Auto Pointer
|
||||||
inline const Poco::AutoPtr<AuthenticatedEncryption> getPassword() {
|
inline const Poco::AutoPtr<AuthenticatedEncryption> getPassword() {
|
||||||
@ -80,10 +90,14 @@ namespace controller {
|
|||||||
std::shared_lock<std::shared_mutex> _lock(mSharedMutex);
|
std::shared_lock<std::shared_mutex> _lock(mSharedMutex);
|
||||||
return !mPassword.isNull();
|
return !mPassword.isNull();
|
||||||
}
|
}
|
||||||
|
inline bool canDecryptPrivateKey() {
|
||||||
|
std::shared_lock<std::shared_mutex> _lock(mSharedMutex);
|
||||||
|
return mCanDecryptPrivateKey;
|
||||||
|
}
|
||||||
inline bool hasPublicKey() {
|
inline bool hasPublicKey() {
|
||||||
return getModel()->getPublicKey();
|
return getModel()->getPublicKey();
|
||||||
}
|
}
|
||||||
//! \brief set key pair, public in model, private if password exist else with next setPassword call into model
|
//! \brief set key pair, public in model, private if password exist else with next setPassword call into model, overwrite existing key pair, not saving into db
|
||||||
//! \param gradidoKeyPair take owner ship
|
//! \param gradidoKeyPair take owner ship
|
||||||
//! \param return 0 if public key set
|
//! \param return 0 if public key set
|
||||||
//! \param return 1 if also private key set (and password exist)
|
//! \param return 1 if also private key set (and password exist)
|
||||||
@ -104,6 +118,8 @@ namespace controller {
|
|||||||
Poco::AutoPtr<AuthenticatedEncryption> mPassword;
|
Poco::AutoPtr<AuthenticatedEncryption> mPassword;
|
||||||
KeyPairEd25519* mGradidoKeyPair;
|
KeyPairEd25519* mGradidoKeyPair;
|
||||||
|
|
||||||
|
bool mCanDecryptPrivateKey;
|
||||||
|
|
||||||
mutable std::shared_mutex mSharedMutex;
|
mutable std::shared_mutex mSharedMutex;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
#include "UserBackups.h"
|
#include "UserBackups.h"
|
||||||
|
|
||||||
|
#include "../Crypto/Passphrase.h"
|
||||||
|
|
||||||
namespace controller {
|
namespace controller {
|
||||||
UserBackups::UserBackups(model::table::UserBackups* dbModel)
|
UserBackups::UserBackups(model::table::UserBackups* dbModel)
|
||||||
{
|
{
|
||||||
@ -61,7 +63,12 @@ namespace controller {
|
|||||||
|
|
||||||
KeyPairEd25519* UserBackups::createGradidoKeyPair()
|
KeyPairEd25519* UserBackups::createGradidoKeyPair()
|
||||||
{
|
{
|
||||||
|
auto model = getModel();
|
||||||
|
auto mnemonicType = model->getMnemonicType();
|
||||||
|
assert(mnemonicType >= 0 && mnemonicType < ServerConfig::MNEMONIC_MAX);
|
||||||
|
auto wordSource = &ServerConfig::g_Mnemonic_WordLists[mnemonicType];
|
||||||
|
Poco::AutoPtr<Passphrase> passphrase = new Passphrase(model->getPassphrase(), wordSource);
|
||||||
|
return KeyPairEd25519::create(passphrase);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string UserBackups::getPassphrase(ServerConfig::Mnemonic_Types type)
|
std::string UserBackups::getPassphrase(ServerConfig::Mnemonic_Types type)
|
||||||
|
|||||||
@ -665,7 +665,7 @@ void Session::finalizeTransaction(bool sign, bool reject)
|
|||||||
|
|
||||||
if (!reject) {
|
if (!reject) {
|
||||||
if (sign) {
|
if (sign) {
|
||||||
Poco::AutoPtr<SigningTransaction> signingTransaction(new SigningTransaction(mCurrentActiveProcessingTransaction, mSessionUser));
|
Poco::AutoPtr<SigningTransaction> signingTransaction(new SigningTransaction(mCurrentActiveProcessingTransaction, mNewUser));
|
||||||
signingTransaction->scheduleTask(signingTransaction);
|
signingTransaction->scheduleTask(signingTransaction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -745,7 +745,27 @@ UserStates Session::loadUser(const std::string& email, const std::string& passwo
|
|||||||
}
|
}
|
||||||
// error decrypting private key
|
// error decrypting private key
|
||||||
if (-2 == loginResult) {
|
if (-2 == loginResult) {
|
||||||
|
// check if we have access to the passphrase, if so we can reencrypt the private key
|
||||||
|
auto user_model = mNewUser->getModel();
|
||||||
|
auto user_backups = controller::UserBackups::load(user_model->getID());
|
||||||
|
for (auto it = user_backups.begin(); it != user_backups.end(); it++) {
|
||||||
|
auto key = (*it)->createGradidoKeyPair();
|
||||||
|
if (key->isTheSame(user_model->getPublicKey())) {
|
||||||
|
auto crypted_private_key = key->getCryptedPrivKey(mNewUser->getPassword());
|
||||||
|
if (crypted_private_key) {
|
||||||
|
user_model->setPrivateKey(crypted_private_key);
|
||||||
|
MemoryManager::getInstance()->releaseMemory(crypted_private_key);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
auto em = ErrorManager::getInstance();
|
||||||
|
em->addError(new Error(functionName, "error reencrypt private key"));
|
||||||
|
em->addError(new ParamError(functionName, "for user with email", user_model->getEmail()));
|
||||||
|
em->sendErrorsAsEmail();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
delete key;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// can be removed if session user isn't used any more
|
// can be removed if session user isn't used any more
|
||||||
if (mNewUser->getModel()->getPasswordHashed() && !mSessionUser->validatePwd(password, this)) {
|
if (mNewUser->getModel()->getPasswordHashed() && !mSessionUser->validatePwd(password, this)) {
|
||||||
@ -1103,7 +1123,7 @@ bool Session::generateKeys(bool savePrivkey, bool savePassphrase)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (savePassphrase) {
|
if (savePassphrase) {
|
||||||
auto user_backup = controller::UserBackups::create(user_model->getID(), passphrase->getString());
|
auto user_backup = controller::UserBackups::create(user_model->getID(), passphrase->getString(), mnemonic_type);
|
||||||
// sync version
|
// sync version
|
||||||
//user_backup->getModel()->insertIntoDB(false);
|
//user_backup->getModel()->insertIntoDB(false);
|
||||||
|
|
||||||
|
|||||||
@ -125,9 +125,12 @@ public:
|
|||||||
|
|
||||||
// ------------------------ Passphrase functions ----------------------------
|
// ------------------------ Passphrase functions ----------------------------
|
||||||
|
|
||||||
|
inline void setPassphrase(Poco::AutoPtr<Passphrase> passphrase) { mNewPassphrase = passphrase; }
|
||||||
|
inline Poco::AutoPtr<Passphrase> getPassphrase() { return mNewPassphrase; }
|
||||||
|
|
||||||
inline void setPassphrase(const std::string& passphrase) { mPassphrase = passphrase; }
|
inline void setPassphrase(const std::string& passphrase) { mPassphrase = passphrase; }
|
||||||
|
|
||||||
inline const std::string& getPassphrase() { return mPassphrase; }
|
inline const std::string& getOldPassphrase() { return mPassphrase; }
|
||||||
bool generatePassphrase();
|
bool generatePassphrase();
|
||||||
bool generateKeys(bool savePrivkey, bool savePassphrase);
|
bool generateKeys(bool savePrivkey, bool savePassphrase);
|
||||||
|
|
||||||
@ -187,6 +190,7 @@ private:
|
|||||||
Poco::AutoPtr<User> mSessionUser;
|
Poco::AutoPtr<User> mSessionUser;
|
||||||
Poco::AutoPtr<controller::User> mNewUser;
|
Poco::AutoPtr<controller::User> mNewUser;
|
||||||
std::string mPassphrase;
|
std::string mPassphrase;
|
||||||
|
Poco::AutoPtr<Passphrase> mNewPassphrase;
|
||||||
Poco::DateTime mLastActivity;
|
Poco::DateTime mLastActivity;
|
||||||
Poco::Net::IPAddress mClientLoginIP;
|
Poco::Net::IPAddress mClientLoginIP;
|
||||||
std::string mLastExternReferer;
|
std::string mLastExternReferer;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user