rework login and setPassword, fix bugs, update to use AuthenticatedEncryption as Poco::AutoPtr

This commit is contained in:
Dario 2020-06-24 14:17:25 +02:00
parent 39e85a959e
commit 5934f7c69e
3 changed files with 67 additions and 47 deletions

View File

@ -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<std::shared_mutex> _lock(mSharedMutex);
auto authenticated_encryption = new AuthenticatedEncryption();
assert(mPassword.isNull());
Poco::AutoPtr<AuthenticatedEncryption> 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<AuthenticatedEncryption> passwd)
{
std::unique_lock<std::shared_mutex> _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();

View File

@ -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<AuthenticatedEncryption> passwd);
inline const AuthenticatedEncryption* getPassword() {
//! \brief return AuthenticatedEncryption Auto Pointer
inline const Poco::AutoPtr<AuthenticatedEncryption> getPassword() {
std::shared_lock<std::shared_mutex> _lock(mSharedMutex);
return mPassword;
}
inline bool hasPassword() {
std::shared_lock<std::shared_mutex> _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<std::shared_mutex> _lock(mSharedMutex);
return mGradidoKeyPair;
}
protected:
User(model::table::User* dbModel);
User(model::table::User* dbModel);
std::string mPublicHex;
AuthenticatedEncryption* mPassword;
Poco::AutoPtr<AuthenticatedEncryption> mPassword;
KeyPairEd25519* mGradidoKeyPair;
mutable std::shared_mutex mSharedMutex;

View File

@ -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)) {