diff --git a/src/cpp/controller/User.cpp b/src/cpp/controller/User.cpp index 3f2fe349f..2579b5472 100644 --- a/src/cpp/controller/User.cpp +++ b/src/cpp/controller/User.cpp @@ -22,10 +22,6 @@ namespace controller { User::~User() { - if (mPassword) { - delete mPassword; - mPassword = nullptr; - } if (mGradidoKeyPair) { delete mGradidoKeyPair; mGradidoKeyPair = nullptr; @@ -131,46 +127,63 @@ namespace controller { int User::login(const std::string& password) { - if (mPassword && mPassword->hasKey()) { + if (!mPassword.isNull() && mPassword->hasKey()) { return 2; } + std::unique_lock _lock(mSharedMutex); - auto authenticated_encryption = new AuthenticatedEncryption(); + assert(mPassword.isNull()); + + Poco::AutoPtr authenticated_encryption(new AuthenticatedEncryption); auto model = getModel(); - assert(authenticated_encryption && model); + assert(!authenticated_encryption.isNull() && model); authenticated_encryption->createKey(model->getEmail(), password); - 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"); MemoryBin* clear_private_key = nullptr; - if (mPassword) delete mPassword; - mPassword = authenticated_encryption; - + // additional check if saved private key found, decrypt and derive public key and compare with saved public key if (!model->hasPrivateKeyEncrypted()) { + mPassword = authenticated_encryption; return 1; } - else { - 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 mPassword; - mPassword = nullptr; - delete gradido_key_pair; + else + { + if (AuthenticatedEncryption::AUTH_DECRYPT_OK == authenticated_encryption->decrypt(model->getPrivateKeyEncrypted(), &clear_private_key)) { + if (mGradidoKeyPair) { + if (mGradidoKeyPair->isTheSame(clear_private_key) == 0) { + mPassword = authenticated_encryption; + return 1; + } + else { + delete mGradidoKeyPair; + mGradidoKeyPair = nullptr; + } + } + mGradidoKeyPair = new KeyPairEd25519(clear_private_key); + if (!mGradidoKeyPair->isTheSame(model->getPublicKey())) { + delete mGradidoKeyPair; + mGradidoKeyPair = nullptr; + //printf("pubkeys don't match\n"); return -1; } - if (mGradidoKeyPair) delete mGradidoKeyPair; - mGradidoKeyPair = gradido_key_pair; - + //printf("correct pwd\n"); + mPassword = authenticated_encryption; return 1; } + else { + //printf("decrypt error\n"); + return -2; + } + } } - delete authenticated_encryption; - + // password didn't match + //printf("password hashed key: %ull, model pwd hashed keys: %ull\n", authenticated_encryption->getKeyHashed(), model->getPasswordHashed()); + //printf("password: %d\n", (int)(mPassword.get())); return 0; } @@ -189,20 +202,15 @@ namespace controller { return 0; } - int User::setPassword(AuthenticatedEncryption* passwd) + int User::setPassword(Poco::AutoPtr passwd) { std::unique_lock _lock(mSharedMutex); auto model = getModel(); - const static char* function_name = "controller::User::setPassword"; - if (mPassword) + if (!mPassword.isNull() && !passwd.isNull()) { // if keys matched - if (*mPassword == *passwd) { - // but separate objects - if (mPassword != passwd) { - delete passwd; - } + if (mPassword->isTheSame(passwd)) { return 0; } // if password exist but gradido key pair not, try to load key pair @@ -210,23 +218,26 @@ namespace controller { //if (!mGradidoKeyPair) mGradidoKeyPair = new KeyPairEd25519; MemoryBin* clear_private_key = nullptr; if (AuthenticatedEncryption::AUTH_DECRYPT_OK == mPassword->decrypt(model->getPrivateKeyEncrypted(), &clear_private_key)) { - if (mGradidoKeyPair) delete mGradidoKeyPair; - mGradidoKeyPair = new KeyPairEd25519(clear_private_key); + if (mGradidoKeyPair && mGradidoKeyPair->isTheSame(clear_private_key) != 0) + { + delete mGradidoKeyPair; + mGradidoKeyPair = nullptr; + } + if (!mGradidoKeyPair) + { + mGradidoKeyPair = new KeyPairEd25519(clear_private_key); + } // check if saved pubkey and from private key extracted pubkey match if (*mGradidoKeyPair != model->getPublicKey()) { delete mGradidoKeyPair; mGradidoKeyPair = nullptr; - delete passwd; return -1; } } } } // replace old password with new - if (mPassword && mPassword != passwd) { - delete mPassword; - } mPassword = passwd; // set new encrypted password and hash @@ -246,6 +257,7 @@ namespace controller { return result; } + int User::checkIfVerificationEmailsShouldBeResend(const Poco::Util::Timer& timer) { auto cm = ConnectionManager::getInstance(); diff --git a/src/cpp/controller/User.h b/src/cpp/controller/User.h index a7bcb96eb..280ca0e7e 100644 --- a/src/cpp/controller/User.h +++ b/src/cpp/controller/User.h @@ -9,6 +9,7 @@ #include "TableControllerBase.h" + namespace controller { /*enum UserLoadedRole { @@ -54,6 +55,7 @@ namespace controller { //! \return 2 already logged in //! \return 0 password didn't match //! \return -1 error saved public key didn't match with private key + //! \return -2 error decrypting private key //! - create authenticated encryption key from password and email //! - compare hash with in db saved hash @@ -67,15 +69,16 @@ namespace controller { //! \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); + int setPassword(Poco::AutoPtr passwd); - inline const AuthenticatedEncryption* getPassword() { + //! \brief return AuthenticatedEncryption Auto Pointer + inline const Poco::AutoPtr getPassword() { std::shared_lock _lock(mSharedMutex); return mPassword; } inline bool hasPassword() { std::shared_lock _lock(mSharedMutex); - return mPassword; + return !mPassword.isNull(); } inline bool hasPublicKey() { return getModel()->getPublicKey(); @@ -86,18 +89,19 @@ namespace controller { //! \param return 1 if also private key set (and password exist) int setGradidoKeyPair(KeyPairEd25519* gradidoKeyPair); + //! \brief return gradido key pair pointer, !!! make sure controller::user stay alive while using it inline const KeyPairEd25519* getGradidoKeyPair() { std::shared_lock _lock(mSharedMutex); return mGradidoKeyPair; } + protected: - User(model::table::User* dbModel); - - + User(model::table::User* dbModel); + std::string mPublicHex; - AuthenticatedEncryption* mPassword; + Poco::AutoPtr mPassword; KeyPairEd25519* mGradidoKeyPair; mutable std::shared_mutex mSharedMutex; diff --git a/src/cpp/model/Session.cpp b/src/cpp/model/Session.cpp index 6ed544be0..1fbe1f04c 100644 --- a/src/cpp/model/Session.cpp +++ b/src/cpp/model/Session.cpp @@ -742,6 +742,10 @@ UserStates Session::loadUser(const std::string& email, const std::string& passwo if (0 == loginResult) { unlock(); return USER_PASSWORD_INCORRECT; + } + // error decrypting private key + if (-2 == loginResult) { + } // can be removed if session user isn't used any more if (mNewUser->getModel()->getPasswordHashed() && !mSessionUser->validatePwd(password, this)) {