diff --git a/CMakeLists.txt b/CMakeLists.txt index 3093c4e80..8f4e05b75 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,6 +37,9 @@ FILE(GLOB PROTO_HEDERA "src/cpp/proto/hedera/*.cc" "src/cpp/proto/hedera/*.h") # used only for test project FILE(GLOB TEST "src/cpp/test/*.cpp" "src/cpp/test/*.h") FILE(GLOB TEST_CRYPTO "src/cpp/test/crypto/*.cpp" "src/cpp/test/crypto/*.h") +FILE(GLOB TEST_MODEL "src/cpp/test/model/*.cpp" "src/cpp/test/model/*.h") +FILE(GLOB TEST_MODEL_TABLE "src/cpp/test/model/table/*.cpp" "src/cpp/test/model/table/*.h") +FILE(GLOB TEST_CONTROLLER "src/cpp/test/controller/*.cpp" "src/cpp/test/controller/*.h") SET(LOCAL_SRCS ${CONTROLLER} ${TINF} ${MAIN} ${HTTPInterface} @@ -44,6 +47,9 @@ SET(LOCAL_SRCS ${SINGLETON_MANAGER} ${LIB_SRC} ${MYSQL} ${TASKS} ${PROTO_GRADIDO} ${PROTO_HEDERA} ) +SET(LOCAL_TEST_SRC + ${TEST} ${TEST_CRYPTO} ${TEST_MODEL} ${TEST_MODEL_TABLE} ${TEST_CONTROLLER} +) aux_source_directory("src/cpp" LOCAL_SRCS) if(MSVC) @@ -63,6 +69,9 @@ source_group("lib" FILES ${LIB_SRC}) source_group("HTTP-Interface" FILES ${HTTPInterface}) source_group("Json-Interface" FILES ${JSONInterface}) source_group("Test\\crypto" FILES ${TEST_CRYPTO}) +source_group("Test\\model\\table" FILES ${TEST_MODEL_TABLE}) +source_group("Test\\model" FILES ${TEST_MODEL}) +source_group("Test\\controller" FILES ${TEST_CONTROLLER}) source_group("Test" FILES ${TEST}) endif(MSVC) @@ -152,7 +161,7 @@ enable_testing() #_TEST_BUILD -add_executable(Gradido_LoginServer_Test ${LOCAL_SRCS} ${TEST} ${TEST_CRYPTO}) +add_executable(Gradido_LoginServer_Test ${LOCAL_SRCS} ${LOCAL_TEST_SRC}) target_compile_definitions(Gradido_LoginServer_Test PUBLIC "_TEST_BUILD") target_link_libraries(Gradido_LoginServer_Test ${CONAN_LIBS} ${IROHA_ED25519}) diff --git a/src/cpp/Crypto/AuthenticatedEncryption.cpp b/src/cpp/Crypto/AuthenticatedEncryption.cpp index 87464f778..0a1625991 100644 --- a/src/cpp/Crypto/AuthenticatedEncryption.cpp +++ b/src/cpp/Crypto/AuthenticatedEncryption.cpp @@ -68,7 +68,7 @@ AuthenticatedEncryption::ResultType AuthenticatedEncryption::createKey(const std return AUTH_ENCRYPT_OK; } -AuthenticatedEncryption::ResultType AuthenticatedEncryption::encrypt(const MemoryBin* message, MemoryBin** encryptedMessage) +AuthenticatedEncryption::ResultType AuthenticatedEncryption::encrypt(const MemoryBin* message, MemoryBin** encryptedMessage) const { assert(message && encryptedMessage); std::shared_lock _lock(mWorkingMutex); @@ -100,7 +100,7 @@ AuthenticatedEncryption::ResultType AuthenticatedEncryption::encrypt(const Memor return AUTH_ENCRYPT_OK; } -AuthenticatedEncryption::ResultType AuthenticatedEncryption::decrypt(const MemoryBin* encryptedMessage, MemoryBin** message) +AuthenticatedEncryption::ResultType AuthenticatedEncryption::decrypt(const MemoryBin* encryptedMessage, MemoryBin** message) const { assert(message && encryptedMessage); std::shared_lock _lock(mWorkingMutex); @@ -128,6 +128,34 @@ AuthenticatedEncryption::ResultType AuthenticatedEncryption::decrypt(const Memor return AUTH_DECRYPT_OK; } +AuthenticatedEncryption::ResultType AuthenticatedEncryption::decrypt(const std::vector& encryptedMessage, MemoryBin** message) const +{ + assert(message); + std::shared_lock _lock(mWorkingMutex); + + if (!mEncryptionKey) { + return AUTH_NO_KEY; + } + + size_t decryptSize = encryptedMessage.size() - crypto_secretbox_MACBYTES; + //unsigned char* decryptBuffer = (unsigned char*)malloc(decryptSize); + auto mm = MemoryManager::getInstance(); + //ObfusArray* decryptedData = new ObfusArray(decryptSize); + auto decryptedData = mm->getFreeMemory(decryptSize); + unsigned char nonce[crypto_secretbox_NONCEBYTES]; + // we use a hardcoded value for nonce + // TODO: use a dynamic value, save it along with the other parameters + memset(nonce, 31, crypto_secretbox_NONCEBYTES); + + if (crypto_secretbox_open_easy(*decryptedData, encryptedMessage.data(), encryptedMessage.size(), nonce, *mEncryptionKey)) { + mm->releaseMemory(decryptedData); + return AUTH_DECRYPT_MESSAGE_FAILED; + } + *message = decryptedData; + + return AUTH_DECRYPT_OK; +} + const char* AuthenticatedEncryption::getErrorMessage(ResultType type) { switch (type) { diff --git a/src/cpp/Crypto/AuthenticatedEncryption.h b/src/cpp/Crypto/AuthenticatedEncryption.h index e11b0cc3f..e3a920ec9 100644 --- a/src/cpp/Crypto/AuthenticatedEncryption.h +++ b/src/cpp/Crypto/AuthenticatedEncryption.h @@ -5,6 +5,7 @@ #include "../SingletonManager/MemoryManager.h" #include +#include /*! * @@ -46,6 +47,9 @@ public: std::shared_lock _lock(mWorkingMutex); return mEncryptionKeyHash == b.getKeyHashed(); } + inline bool operator == (const KeyHashed& hash) const { + return mEncryptionKeyHash == hash; + } inline bool hasKey() const { std::shared_lock _lock(mWorkingMutex); return mEncryptionKey != nullptr; } @@ -56,11 +60,16 @@ public: //! \return AUTH_CREATE_ENCRYPTION_KEY_FAILED call strerror(errno) for more details ResultType createKey(const std::string& salt_parameter, const std::string& passwd); - ResultType encrypt(const MemoryBin* message, MemoryBin** encryptedMessage); + ResultType encrypt(const MemoryBin* message, MemoryBin** encryptedMessage) const; - ResultType decrypt(const MemoryBin* encryptedMessage, MemoryBin** message); + ResultType decrypt(const MemoryBin* encryptedMessage, MemoryBin** message) const; + //! \brief same as the other decrypt only in other format + //! \param encryptedMessage format from Poco Binary Data from DB, like returned from model/table/user for encrypted private key + //! + //! double code, I don't know how to prevent without unnecessary copy of encryptedMessage + ResultType decrypt(const std::vector& encryptedMessage, MemoryBin** message) const; - const char* getErrorMessage(ResultType type); + static const char* getErrorMessage(ResultType type); protected: // algorithms parameter @@ -75,4 +84,6 @@ protected: mutable std::shared_mutex mWorkingMutex; }; + + #endif //__GRADIDO_LOGIN_SERVER_CRYPTO_AUTHENTICATED_ENCRYPTION_H \ No newline at end of file diff --git a/src/cpp/Crypto/IKeyPair.h b/src/cpp/Crypto/IKeyPair.h index 584631326..2659b211a 100644 --- a/src/cpp/Crypto/IKeyPair.h +++ b/src/cpp/Crypto/IKeyPair.h @@ -17,7 +17,7 @@ class IKeyPair { public: //! \return caller take ownership of return value - virtual MemoryBin* sign(const MemoryBin* message) = 0; + virtual MemoryBin* sign(const MemoryBin* message) const = 0 ; }; diff --git a/src/cpp/Crypto/KeyPairEd25519.cpp b/src/cpp/Crypto/KeyPairEd25519.cpp index 7b5d0541a..e06ff02d8 100644 --- a/src/cpp/Crypto/KeyPairEd25519.cpp +++ b/src/cpp/Crypto/KeyPairEd25519.cpp @@ -8,10 +8,13 @@ #include "Passphrase.h" -KeyPairEd25519::KeyPairEd25519(MemoryBin* privateKey, const unsigned char* publicKey) +KeyPairEd25519::KeyPairEd25519(MemoryBin* privateKey) : mSodiumSecret(privateKey) { - memcpy(mSodiumPublic, publicKey, crypto_sign_PUBLICKEYBYTES); + //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(mSodiumPublic, *privateKey); } KeyPairEd25519::KeyPairEd25519(const unsigned char* publicKey) @@ -93,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 @@ -105,7 +109,7 @@ KeyPairEd25519* KeyPairEd25519::create(const Passphrase* passphrase) // using } -MemoryBin* KeyPairEd25519::sign(const MemoryBin* message) +MemoryBin* KeyPairEd25519::sign(const MemoryBin* message) const { if (!message || !message->size()) return nullptr; @@ -146,4 +150,19 @@ MemoryBin* KeyPairEd25519::sign(const MemoryBin* message) return signBinBuffer; +} + +MemoryBin* KeyPairEd25519::getCryptedPrivKey(const AuthenticatedEncryption* password) const +{ + if (!password) return nullptr; + if (!mSodiumSecret) return nullptr; + + MemoryBin* encryptedKey = nullptr; + if (AuthenticatedEncryption::AUTH_ENCRYPT_OK == password->encrypt(mSodiumSecret, &encryptedKey)) { + return encryptedKey; + } + else { + return nullptr; + } + } \ No newline at end of file diff --git a/src/cpp/Crypto/KeyPairEd25519.h b/src/cpp/Crypto/KeyPairEd25519.h index 9efe2e046..839b1cfc0 100644 --- a/src/cpp/Crypto/KeyPairEd25519.h +++ b/src/cpp/Crypto/KeyPairEd25519.h @@ -12,6 +12,7 @@ */ #include "sodium.h" +#include "AuthenticatedEncryption.h" class Passphrase; @@ -20,7 +21,7 @@ class KeyPairEd25519 : public IKeyPair public: //! \param privateKey: take ownership, release after object destruction //! \param publicKey: copy - KeyPairEd25519(MemoryBin* privateKey, const unsigned char* publicKey); + KeyPairEd25519(MemoryBin* privateKey); KeyPairEd25519(const unsigned char* publicKey); ~KeyPairEd25519(); @@ -30,20 +31,30 @@ public: static KeyPairEd25519* create(const Passphrase* passphrase); //! \return caller take ownership of return value - MemoryBin* sign(const MemoryBin* message); + MemoryBin* sign(const MemoryBin* message) const; inline const unsigned char* getPublicKey() const { return mSodiumPublic; } inline bool isTheSame(const KeyPairEd25519& b) const { return 0 == sodium_memcmp(mSodiumPublic, b.mSodiumPublic, crypto_sign_PUBLICKEYBYTES); } + inline bool isTheSame(const unsigned char* pubkey) const { + return 0 == sodium_memcmp(mSodiumPublic, pubkey, crypto_sign_PUBLICKEYBYTES); + } inline bool operator == (const KeyPairEd25519& b) const { return isTheSame(b); } inline bool operator != (const KeyPairEd25519& b) const { return !isTheSame(b); } + inline bool operator == (const unsigned char* b) const { return isTheSame(b); } + inline bool operator != (const unsigned char* b) const { return !isTheSame(b); } + inline bool hasPrivateKey() const { return mSodiumSecret != nullptr; } + //! \brief only way to get a private key.. encrypted + MemoryBin* getCryptedPrivKey(const AuthenticatedEncryption* password) const; + protected: + KeyPairEd25519(); diff --git a/src/cpp/Crypto/Passphrase.cpp b/src/cpp/Crypto/Passphrase.cpp index 743747bbc..421cca11b 100644 --- a/src/cpp/Crypto/Passphrase.cpp +++ b/src/cpp/Crypto/Passphrase.cpp @@ -3,6 +3,7 @@ #include "Poco/Types.h" #include "Poco/Tuple.h" + #include "../SingletonManager/ErrorManager.h" #include "KeyPairEd25519.h" @@ -163,10 +164,88 @@ Poco::AutoPtr Passphrase::create(const Poco::UInt16 wordIndices[PHRA clearPassphrase += word; clearPassphrase += " "; } + else { + return nullptr; + } } return new Passphrase(clearPassphrase, wordSource); } +Poco::AutoPtr Passphrase::generate(const Mnemonic* wordSource) +{ + auto em = ErrorManager::getInstance(); + auto mm = MemoryManager::getInstance(); + auto word_indices = mm->getFreeMemory(PHRASE_WORD_COUNT * sizeof(Poco::UInt16)); + Poco::UInt16* word_indices_p = (Poco::UInt16*)word_indices->data(); + + for (int i = 0; i < PHRASE_WORD_COUNT; i++) { + word_indices_p[i] = randombytes_random() % 2048; + } + auto result_passphrase = create(word_indices_p, wordSource); + mm->releaseMemory(word_indices); + + return result_passphrase; + /* + + unsigned int random_indices[PHRASE_WORD_COUNT]; + + unsigned int str_sizes[PHRASE_WORD_COUNT]; + unsigned int phrase_buffer_size = 0; + static const char* function_name = "Passphrase::generate"; + bool error_reloading_mnemonic_word_list = false; + int loop_trys = 0; + Poco::RegularExpression check_valid_word("^[a-zA-ZÄÖÜäöüß&;]*$"); + + // TODO: make sure words didn't double + for (int i = 0; i < PHRASE_WORD_COUNT; i++) { + random_indices[i] = randombytes_random() % 2048; + auto word = wordSource->getWord(random_indices[i]); + if (loop_trys > 10 || error_reloading_mnemonic_word_list) { + return nullptr; + } + if (!word) { + em->addError(new ParamError(function_name, "empty word get for index", random_indices[i])); + em->sendErrorsAsEmail(); + + random_indices[i] = randombytes_random() % 2048; + word = wordSource->getWord(random_indices[i]); + if (!word) return nullptr; + + } + else { + if (!check_valid_word.match(word, 0, Poco::RegularExpression::RE_NOTEMPTY)) { + em->addError(new ParamError(function_name, "invalid word", word)); + em->addError(new Error(function_name, "try to reload mnemonic word list, but this error is maybe evidence for a serious memory problem!!!")); + if (!ServerConfig::loadMnemonicWordLists()) { + em->addError(new Error(function_name, "error reloading mnemonic word lists")); + error_reloading_mnemonic_word_list = true; + } + else { + i = 0; + loop_trys++; + } + em->sendErrorsAsEmail(); + } + } + str_sizes[i] = strlen(word); + phrase_buffer_size += str_sizes[i]; + } + phrase_buffer_size += PHRASE_WORD_COUNT + 1; + + std::string phrase_buffer(phrase_buffer_size, '\0'); + int phrase_buffer_cursor = 0; + + for (int i = 0; i < PHRASE_WORD_COUNT; i++) { + memcpy(&phrase_buffer[phrase_buffer_cursor], wordSource->getWord(random_indices[i]), str_sizes[i]); + + phrase_buffer_cursor += str_sizes[i]; + phrase_buffer[phrase_buffer_cursor++] = ' '; + } + + + return create(; + */ +} bool Passphrase::createWordIndices() { diff --git a/src/cpp/Crypto/Passphrase.h b/src/cpp/Crypto/Passphrase.h index 6d9a31965..e559e9471 100644 --- a/src/cpp/Crypto/Passphrase.h +++ b/src/cpp/Crypto/Passphrase.h @@ -16,6 +16,8 @@ public: static Poco::AutoPtr create(const Poco::UInt16 wordIndices[PHRASE_WORD_COUNT], const Mnemonic* wordSource); static Poco::AutoPtr create(const MemoryBin* wordIndices, const Mnemonic* wordSource); + //! \brief generate new passphrase with random + static Poco::AutoPtr generate(const Mnemonic* wordSource); static const Mnemonic* detectMnemonic(const std::string& passphrase, const KeyPairEd25519* keyPair = nullptr); //! \brief transform passphrase into another language/mnemonic source diff --git a/src/cpp/Crypto/mnemonic.cpp b/src/cpp/Crypto/mnemonic.cpp index bf8d2fd7d..53fa3d781 100644 --- a/src/cpp/Crypto/mnemonic.cpp +++ b/src/cpp/Crypto/mnemonic.cpp @@ -9,6 +9,13 @@ #include "DRRandom.h" +#include "../SingletonManager/ErrorManager.h" +#include "../ServerConfig.h" + +#include "Poco/RegularExpression.h" + +static Poco::RegularExpression g_checkValidWord("^[a-zA-ZÄÖÜäöüß&;]*$"); + Mnemonic::Mnemonic() { memset(mWords, 0, 2048); @@ -180,6 +187,49 @@ bool Mnemonic::isWordExist(const std::string& word) const } */ +const char* Mnemonic::getWord(short index) const { + //std::shared_lock _lock(mWorkingMutex); + + if (index < 2048 && index >= 0) { + std::string word; + { + std::shared_lock _lock(mWorkingMutex); + word = mWords[index]; + } + + if (!g_checkValidWord.match(word, 0, Poco::RegularExpression::RE_NOTEMPTY)) { + auto em = ErrorManager::getInstance(); + const char* function_name = "Mnemonic::getWord"; + em->addError(new ParamError(function_name, "invalid word", word)); + em->addError(new Error(function_name, "try to reload mnemonic word list, but this error is maybe evidence for a serious memory problem!!!")); + + if (!ServerConfig::loadMnemonicWordLists()) { + em->addError(new Error(function_name, "error reloading mnemonic word lists")); + em->sendErrorsAsEmail(); + return nullptr; + } + + { + std::shared_lock _lock(mWorkingMutex); + word = mWords[index]; + } + if (!g_checkValidWord.match(word, 0, Poco::RegularExpression::RE_NOTEMPTY)) { + em->addError(new Error(function_name, "word invalid after reload mnemonic word lists")); + em->sendErrorsAsEmail(); + return nullptr; + } + em->sendErrorsAsEmail(); + + } + + { + std::shared_lock _lock(mWorkingMutex); + return mWords[index]; + } + } + return nullptr; +} + void Mnemonic::clear() { //Poco::Mutex::ScopedLock _lock(mWorkingMutex, 500); diff --git a/src/cpp/Crypto/mnemonic.h b/src/cpp/Crypto/mnemonic.h index 7d9a848b7..ccdb85a73 100644 --- a/src/cpp/Crypto/mnemonic.h +++ b/src/cpp/Crypto/mnemonic.h @@ -30,11 +30,7 @@ public: int init(void(*fill_words_func)(unsigned char*), unsigned int original_size, unsigned int compressed_size); - inline const char* getWord(short index) const { - std::shared_lock _lock(mWorkingMutex); - if (index < 2048 && index >= 0) return mWords[index]; - return nullptr; - } + const char* getWord(short index) const; short getWordIndex(const char* word) const; inline bool isWordExist(const std::string& word) const { std::shared_lock _lock(mWorkingMutex); diff --git a/src/cpp/HTTPInterface/AdminUserPasswordReset.cpp b/src/cpp/HTTPInterface/AdminUserPasswordReset.cpp index 4ab46bf67..fe41d3143 100644 --- a/src/cpp/HTTPInterface/AdminUserPasswordReset.cpp +++ b/src/cpp/HTTPInterface/AdminUserPasswordReset.cpp @@ -207,7 +207,7 @@ void AdminUserPasswordReset::handleRequest(Poco::Net::HTTPServerRequest& request responseStream << "\n"; responseStream << "\t\t\t
  • Private Key verschlüsselt: "; #line 92 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminUserPasswordReset.cpsp" - responseStream << ( std::to_string(userModel->existPrivateKeyCrypted()) ); + responseStream << ( std::to_string(userModel->hasPrivateKeyEncrypted()) ); responseStream << "
  • \n"; responseStream << "\t\t\t
  • Passwort gesetzt: "; #line 93 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminUserPasswordReset.cpsp" diff --git a/src/cpp/HTTPInterface/LoginPage.cpp b/src/cpp/HTTPInterface/LoginPage.cpp index 7d5b4d73f..756cb2c61 100644 --- a/src/cpp/HTTPInterface/LoginPage.cpp +++ b/src/cpp/HTTPInterface/LoginPage.cpp @@ -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 << "
    \n"; responseStream << "
    \n"; responseStream << " \n"; responseStream << "\t\t\t\n"; responseStream << "\t\t\t\t\n"; responseStream << "\t\t\t\t \n"; responseStream << "\t\t\t\t\"logo\"\n"; responseStream << "\t\t\t\n"; @@ -247,14 +250,14 @@ void LoginPage::handleRequest(Poco::Net::HTTPServerRequest& request, Poco::Net:: responseStream << "
    \n"; responseStream << "\t\t\t
    \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
    \n"; responseStream << "
    \n"; responseStream << " \n"; responseStream << "\t\t\t \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
    \n"; responseStream << "
    \n"; responseStream << "
    \n"; responseStream << "
    \n"; responseStream << " 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 << "
    \n"; responseStream << "
    \n"; responseStream << " gettext("Password") ); responseStream << "\" />\n"; responseStream << "
    \n"; responseStream << " \n"; responseStream << "
    \n"; responseStream << "\t\t\t\t\t\n"; diff --git a/src/cpp/HTTPInterface/PageRequestHandlerFactory.cpp b/src/cpp/HTTPInterface/PageRequestHandlerFactory.cpp index 8b303971a..9a5eb43c3 100644 --- a/src/cpp/HTTPInterface/PageRequestHandlerFactory.cpp +++ b/src/cpp/HTTPInterface/PageRequestHandlerFactory.cpp @@ -26,7 +26,7 @@ #include "TranslatePassphrase.h" #include "PassphrasedTransaction.h" #include "AdminUserPasswordReset.h" - +#include "RegisterDirectPage.h" #include "DecodeTransactionPage.h" #include "RepairDefectPassphrase.h" @@ -119,6 +119,11 @@ Poco::Net::HTTPRequestHandler* PageRequestHandlerFactory::createRequestHandler(c pageRequestHandler->setProfiler(timeUsed); return pageRequestHandler; } + if (url_first_part == "/registerDirect") { + auto pageRequestHandler = new RegisterDirectPage; + pageRequestHandler->setProfiler(timeUsed); + return pageRequestHandler; + } if (url_first_part == "/resetPassword") { auto resetPassword = new ResetPassword; resetPassword->setProfiler(timeUsed); diff --git a/src/cpp/SingletonManager/MemoryManager.cpp b/src/cpp/SingletonManager/MemoryManager.cpp index 132ec94de..2c6e98ca7 100644 --- a/src/cpp/SingletonManager/MemoryManager.cpp +++ b/src/cpp/SingletonManager/MemoryManager.cpp @@ -118,6 +118,7 @@ MemoryManager::MemoryManager() mMemoryPageStacks[2] = new MemoryPageStack(65); // pubkey hex mMemoryPageStacks[3] = new MemoryPageStack(96); // privkey encrypted mMemoryPageStacks[4] = new MemoryPageStack(161); // privkey hex + mMemoryPageStacks[5] = new MemoryPageStack(48); // word indices } MemoryManager::~MemoryManager() @@ -135,6 +136,7 @@ Poco::Int8 MemoryManager::getMemoryStackIndex(Poco::UInt16 size) case 65: return 2; case 96: return 3; case 161: return 4; + case 48: return 5; default: return -1; } return -1; diff --git a/src/cpp/SingletonManager/MemoryManager.h b/src/cpp/SingletonManager/MemoryManager.h index b010fa362..7cb9233f7 100644 --- a/src/cpp/SingletonManager/MemoryManager.h +++ b/src/cpp/SingletonManager/MemoryManager.h @@ -85,7 +85,7 @@ protected: Poco::Int8 getMemoryStackIndex(Poco::UInt16 size); MemoryManager(); - MemoryPageStack* mMemoryPageStacks[5]; + MemoryPageStack* mMemoryPageStacks[6]; }; diff --git a/src/cpp/controller/User.cpp b/src/cpp/controller/User.cpp index 0a9473d9d..78a6ed6c3 100644 --- a/src/cpp/controller/User.cpp +++ b/src/cpp/controller/User.cpp @@ -3,15 +3,26 @@ #include "sodium.h" #include "../SingletonManager/SessionManager.h" +#include "../lib/DataTypeConverter.h" + namespace controller { User::User(model::table::User* dbModel) + : mPassword(nullptr), mGradidoKeyPair(nullptr) { mDBModel = dbModel; } User::~User() { + if (mPassword) { + delete mPassword; + mPassword = nullptr; + } + if (mGradidoKeyPair) { + delete mGradidoKeyPair; + mGradidoKeyPair = nullptr; + } } @@ -111,4 +122,106 @@ namespace controller { return json; } + int User::login(const std::string& password) + { + if (mPassword && mPassword->hasKey()) { + return 2; + } + std::unique_lock _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; + } + + void User::setGradidoKeyPair(KeyPairEd25519* gradidoKeyPair) + { + assert(gradidoKeyPair); + std::unique_lock _lock(mSharedMutex); + if (mGradidoKeyPair) delete mGradidoKeyPair; + mGradidoKeyPair = gradidoKeyPair; + getModel()->setPublicKey(mGradidoKeyPair->getPublicKey()); + } + + int User::setPassword(AuthenticatedEncryption* passwd) + { + std::unique_lock _lock(mSharedMutex); + auto model = getModel(); + const static char* function_name = "controller::User::setPassword"; + + if (mPassword) + { + // 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; + 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); + + // 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 + model->setPasswordHashed(mPassword->getKeyHashed()); + 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 result; + } + } \ No newline at end of file diff --git a/src/cpp/controller/User.h b/src/cpp/controller/User.h index fdfbddf57..01d24c3ff 100644 --- a/src/cpp/controller/User.h +++ b/src/cpp/controller/User.h @@ -2,7 +2,10 @@ #define GRADIDO_LOGIN_SERVER_CONTROLLER_USER_INCLUDE #include "../model/table/User.h" +//#include "../Crypto/AuthenticatedEncryption.h" +#include "../Crypto/KeyPairEd25519.h" +#include #include "TableControllerBase.h" @@ -34,17 +37,52 @@ namespace controller { inline Poco::AutoPtr getModel() { return _getModel(); } inline const model::table::User* getModel() const { return _getModel(); } - 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, 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); + + inline const AuthenticatedEncryption* getPassword() { + std::shared_lock _lock(mSharedMutex); + return mPassword; + } + //! \brief set key pair, public in model, private with next setPassword call into model + //! \param gradidoKeyPair take owner ship + void setGradidoKeyPair(KeyPairEd25519* gradidoKeyPair); + + inline const KeyPairEd25519* getGradidoKeyPair() { + std::shared_lock _lock(mSharedMutex); + return mGradidoKeyPair; + } protected: User(model::table::User* dbModel); + + std::string mPublicHex; + AuthenticatedEncryption* mPassword; + KeyPairEd25519* mGradidoKeyPair; + mutable std::shared_mutex mSharedMutex; }; } diff --git a/src/cpp/model/Session.cpp b/src/cpp/model/Session.cpp index 9c4a44650..e5be916c4 100644 --- a/src/cpp/model/Session.cpp +++ b/src/cpp/model/Session.cpp @@ -15,9 +15,13 @@ #include "../tasks/PrepareEmailTask.h" #include "../tasks/SendEmailTask.h" #include "../tasks/SigningTransaction.h" +#include "../tasks/AuthenticatedEncryptionCreateKeyTask.h" #include "../lib/JsonRequest.h" +#include "../Crypto/Passphrase.h" + + #include "../controller/User.h" #include "../controller/UserBackups.h" #include "../controller/EmailVerificationCode.h" @@ -313,6 +317,65 @@ bool Session::createUser(const std::string& first_name, const std::string& last_ return true; } +bool Session::createUserDirect(const std::string& first_name, const std::string& last_name, const std::string& email, const std::string& password) +{ + static const char* function_name = "Session::createUserDirect"; + auto sm = SessionManager::getInstance(); + auto em = ErrorManager::getInstance(); + + if (!sm->isValid(first_name, VALIDATE_NAME)) { + addError(new Error(gettext("Vorname"), gettext("Bitte gebe einen Namen an. Mindestens 3 Zeichen, keines folgender Zeichen <>&;")), false); + return false; + } + if (!sm->isValid(last_name, VALIDATE_NAME)) { + addError(new Error(gettext("Nachname"), gettext("Bitte gebe einen Namen an. Mindestens 3 Zeichen, keines folgender Zeichen <>&;")), false); + return false; + } + if (!sm->isValid(email, VALIDATE_EMAIL)) { + addError(new Error(gettext("E-Mail"), gettext("Bitte gebe eine gültige E-Mail Adresse an.")), false); + return false; + } + if (!sm->checkPwdValidation(password, this)) { + return false; + } + + // check if email already exist + auto user = controller::User::create(); + if (user->load(email) >= 1) { + addError(new Error(gettext("E-Mail"), gettext("Für diese E-Mail Adresse gibt es bereits ein Konto")), false); + return false; + } + + mNewUser = controller::User::create(email, first_name, last_name); + auto user_model = mNewUser->getModel(); + user_model->insertIntoDB(true); + auto user_id = user_model->getID(); + + + // one retry in case of connection error + if (!user_id) { + user_model->insertIntoDB(true); + auto user_id = user_model->getID(); + if (!user_id) { + em->addError(new ParamError(function_name, "error saving new user in db, after one retry with email", email)); + em->sendErrorsAsEmail(); + addError(new Error(gettext("Server"), gettext("Fehler beim speichen des Kontos bitte versuche es später noch einmal")), false); + return false; + } + } + auto passphrase = Passphrase::generate(&ServerConfig::g_Mnemonic_WordLists[ServerConfig::MNEMONIC_GRADIDO_BOOK_GERMAN_RANDOM_ORDER_FIXED_CASES]); + if (passphrase.isNull()) { + em->addError(new ParamError(function_name, "error generating passphrase for", email)); + em->sendErrorsAsEmail(); + } + auto gradido_key_pair = KeyPairEd25519::create(passphrase); + mNewUser->setGradidoKeyPair(gradido_key_pair); + UniLib::controller::TaskPtr create_authenticated_encrypten_key = new AuthenticatedEncryptionCreateKeyTask(mNewUser, password); + create_authenticated_encrypten_key->scheduleTask(create_authenticated_encrypten_key); + + return true; +} + bool Session::ifUserExist(const std::string& email) { auto em = ErrorManager::getInstance(); @@ -631,6 +694,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 +702,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 +717,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; diff --git a/src/cpp/model/Session.h b/src/cpp/model/Session.h index 34cedfae5..6aec94671 100644 --- a/src/cpp/model/Session.h +++ b/src/cpp/model/Session.h @@ -77,6 +77,9 @@ public: // create User send e-mail activation link bool createUser(const std::string& first_name, const std::string& last_name, const std::string& email, const std::string& password); + //! \brief new register function, without showing user pubkeys, using controller/user + bool createUserDirect(const std::string& first_name, const std::string& last_name, const std::string& email, const std::string& password); + // adminRegister without passwort bool adminCreateUser(const std::string& first_name, const std::string& last_name, const std::string& email); diff --git a/src/cpp/model/User.cpp b/src/cpp/model/User.cpp index a36ba62b4..fdba4b0b3 100644 --- a/src/cpp/model/User.cpp +++ b/src/cpp/model/User.cpp @@ -426,8 +426,8 @@ User::User(Poco::AutoPtr ctrl_user) mPublicHex = std::string((char*)(*hexStringTemp)); mm->releaseMemory(hexStringTemp); } - if (model->existPrivateKeyCrypted()) { - auto privKeyVetor = model->getPrivateKeyCrypted(); + if (model->hasPrivateKeyEncrypted()) { + auto privKeyVetor = model->getPrivateKeyEncrypted(); mPrivateKey = mm->getFreeMemory(privKeyVetor.size()); memcpy(*mPrivateKey, privKeyVetor.data(), privKeyVetor.size()); } diff --git a/src/cpp/model/User.h b/src/cpp/model/User.h index 54effae90..698abd44c 100644 --- a/src/cpp/model/User.h +++ b/src/cpp/model/User.h @@ -35,6 +35,7 @@ enum UserStates USER_EMAIL_NOT_ACTIVATED, USER_NO_KEYS, USER_NO_PRIVATE_KEY, + USER_KEYS_DONT_MATCH, USER_COMPLETE }; diff --git a/src/cpp/model/table/User.cpp b/src/cpp/model/table/User.cpp index ddc4b6c8c..a407c4cf7 100644 --- a/src/cpp/model/table/User.cpp +++ b/src/cpp/model/table/User.cpp @@ -143,7 +143,10 @@ namespace model { size_t User::updatePrivkey() { lock(); - if (mPrivateKey.isNull()) return 0; + if (mPrivateKey.isNull()) { + unlock(); + return 0; + } auto result = updateIntoDB("privkey", mPrivateKey.value()); unlock(); return result; @@ -151,12 +154,45 @@ namespace model { size_t User::updatePublickey() { lock(); - if (mPublicKey.isNull()) return 0; + if (mPublicKey.isNull()) { + unlock(); + return 0; + } auto result = updateIntoDB("pubkey", mPublicKey.value()); unlock(); return result; } + size_t User::updatePrivkeyAndPasswordHash() + { + lock(); + if (mPrivateKey.isNull() || !mPasswordHashed || !mID) { + unlock(); + return 0; + } + auto cm = ConnectionManager::getInstance(); + auto session = cm->getConnection(CONNECTION_MYSQL_LOGIN_SERVER); + + Poco::Data::Statement update(session); + + update << "UPDATE users SET password = ?, privkey = ? where id = ?;", + bind(mPasswordHashed), use(mPrivateKey), use(mID); + + + size_t resultCount = 0; + try { + return update.execute(); + } + catch (Poco::Exception& ex) { + lock("User::updatePrivkeyAndPasswordHash"); + addError(new ParamError(getTableName(), "mysql error by insert", ex.displayText().data())); + addError(new ParamError(getTableName(), "data set: ", toString().data())); + unlock(); + } + //printf("data valid: %s\n", toString().data()); + return 0; + } + /* std::string mEmail; diff --git a/src/cpp/model/table/User.h b/src/cpp/model/table/User.h index d9f1bd10f..6e6b6f86f 100644 --- a/src/cpp/model/table/User.h +++ b/src/cpp/model/table/User.h @@ -45,7 +45,7 @@ namespace model { // specific db operation size_t updatePrivkey(); size_t updatePublickey(); - + size_t updatePrivkeyAndPasswordHash(); // default getter unlocked inline const std::string& getEmail() const { return mEmail; } @@ -56,8 +56,8 @@ namespace model { inline const unsigned char* getPublicKey() const { if (mPublicKey.isNull()) return nullptr; return mPublicKey.value().content().data(); } std::string getPublicKeyHex() const; - inline bool existPrivateKeyCrypted() const { return !mPrivateKey.isNull(); } - inline const std::vector& getPrivateKeyCrypted() const { return mPrivateKey.value().content(); } + inline bool hasPrivateKeyEncrypted() const { return !mPrivateKey.isNull(); } + inline const std::vector& getPrivateKeyEncrypted() const { return mPrivateKey.value().content(); } inline bool isEmailChecked() const { return mEmailChecked; } inline const std::string& getLanguageKey() const { return mLanguageKey; } @@ -67,7 +67,8 @@ namespace model { inline void setLastName(const std::string& last_name) { mLastName = last_name; } inline void setPasswordHashed(const Poco::UInt64& passwordHashed) { mPasswordHashed = passwordHashed; } void setPublicKey(const unsigned char* publicKey); - // copy data, didn't move memory bin + //! \brief set encrypted private key + //! \param privateKey copy data, didn't move memory bin void setPrivateKey(const MemoryBin* privateKey); inline void setEmailChecked(bool emailChecked) { mEmailChecked = emailChecked; } inline void setLanguageKey(const std::string& languageKey) { mLanguageKey = languageKey; } diff --git a/src/cpp/tasks/AuthenticatedEncryptionCreateKeyTask.cpp b/src/cpp/tasks/AuthenticatedEncryptionCreateKeyTask.cpp new file mode 100644 index 000000000..eea68d506 --- /dev/null +++ b/src/cpp/tasks/AuthenticatedEncryptionCreateKeyTask.cpp @@ -0,0 +1,39 @@ +#include "AuthenticatedEncryptionCreateKeyTask.h" + +#include "../ServerConfig.h" +#include "../SingletonManager/SingletonTaskObserver.h" +#include "../SingletonManager/ErrorManager.h" + +#include "../lib/Profiler.h" + +AuthenticatedEncryptionCreateKeyTask::AuthenticatedEncryptionCreateKeyTask(Poco::AutoPtr user, const std::string& passwd) + : UniLib::controller::CPUTask(ServerConfig::g_CryptoCPUScheduler), mUser(user), mPassword(passwd) +{ + SingletonTaskObserver::getInstance()->addTask(mUser->getModel()->getEmail(), TASK_OBSERVER_PASSWORD_CREATION); +} + +AuthenticatedEncryptionCreateKeyTask::~AuthenticatedEncryptionCreateKeyTask() +{ + SingletonTaskObserver::getInstance()->removeTask(mUser->getModel()->getEmail(), TASK_OBSERVER_PASSWORD_CREATION); +} + +int AuthenticatedEncryptionCreateKeyTask::run() +{ + auto em = ErrorManager::getInstance(); + const static char* function_name = "AuthenticatedEncryptionCreateKeyTask::run"; + auto authenticated_encryption = new AuthenticatedEncryption; + Profiler timeUsed; + if (AuthenticatedEncryption::AUTH_ENCRYPT_OK != authenticated_encryption->createKey(mUser->getModel()->getEmail(), mPassword)) { + em->addError(new Error(function_name, "error creating key")); + em->addError(new ParamError(function_name, "for email", mUser->getModel()->getEmail())); + em->addError(new ParamError(function_name, "strerror: ", strerror(errno))); + em->sendErrorsAsEmail(); + return -1; + } + printf("create password time: %s\n", timeUsed.string().data()); + timeUsed.reset(); + mUser->setPassword(authenticated_encryption); + printf("set password time: %s\n", timeUsed.string().data()); + + return 0; +} \ No newline at end of file diff --git a/src/cpp/tasks/AuthenticatedEncryptionCreateKeyTask.h b/src/cpp/tasks/AuthenticatedEncryptionCreateKeyTask.h new file mode 100644 index 000000000..198403a71 --- /dev/null +++ b/src/cpp/tasks/AuthenticatedEncryptionCreateKeyTask.h @@ -0,0 +1,20 @@ +#ifndef __GRADIDO_LOGIN_SERVER_TASKS_AUTHENTICATED_ENCRYPTION_CREATE_KEY_TASK_H +#define __GRADIDO_LOGIN_SERVER_TASKS_AUTHENTICATED_ENCRYPTION_CREATE_KEY_TASK_H + +#include "CPUTask.h" +#include "../controller/User.h" + +class AuthenticatedEncryptionCreateKeyTask : public UniLib::controller::CPUTask +{ +public: + AuthenticatedEncryptionCreateKeyTask(Poco::AutoPtr user, const std::string& passwd); + virtual ~AuthenticatedEncryptionCreateKeyTask(); + + int run(); + const char* getResourceType() const { return "AuthenticatedEncryptionCreateKeyTask"; }; +protected: + Poco::AutoPtr mUser; + std::string mPassword; +}; + +#endif //__GRADIDO_LOGIN_SERVER_TASKS_AUTHENTICATED_ENCRYPTION_CREATE_KEY_TASK_H \ No newline at end of file diff --git a/src/cpp/test/controller/TestUser.cpp b/src/cpp/test/controller/TestUser.cpp new file mode 100644 index 000000000..fc8f8389b --- /dev/null +++ b/src/cpp/test/controller/TestUser.cpp @@ -0,0 +1,10 @@ +#include "TestUser.h" + +namespace controller { + void TestUser::SetUp() + { + + } + + //TEST_F(TestUser, ) +} \ No newline at end of file diff --git a/src/cpp/test/controller/TestUser.h b/src/cpp/test/controller/TestUser.h new file mode 100644 index 000000000..8abe23e7a --- /dev/null +++ b/src/cpp/test/controller/TestUser.h @@ -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 \ No newline at end of file diff --git a/src/cpp/test/crypto/TestAuthenticatedEncryption.cpp b/src/cpp/test/crypto/TestAuthenticatedEncryption.cpp index 22c6a9dfe..93c19bc9b 100644 --- a/src/cpp/test/crypto/TestAuthenticatedEncryption.cpp +++ b/src/cpp/test/crypto/TestAuthenticatedEncryption.cpp @@ -9,13 +9,6 @@ void TestAuthenticatedEncryption::SetUp() { - if (!ServerConfig::g_CryptoAppSecret) { - ServerConfig::g_CryptoAppSecret = DataTypeConverter::hexToBin("21ffbbc616fe"); - } - if (!ServerConfig::g_ServerCryptoKey) { - auto serverKey = DataTypeConverter::hexToBin("a51ef8ac7ef1abf162fb7a65261acd7a"); - ServerConfig::g_ServerCryptoKey = new ObfusArray(serverKey->size(), *serverKey); - } } TEST_F(TestAuthenticatedEncryption, encryptDecryptTest) { diff --git a/src/cpp/test/crypto/TestPassphrase.cpp b/src/cpp/test/crypto/TestPassphrase.cpp index 747d953b9..128a461f6 100644 --- a/src/cpp/test/crypto/TestPassphrase.cpp +++ b/src/cpp/test/crypto/TestPassphrase.cpp @@ -84,7 +84,7 @@ void PassphraseTest::SetUp() wordIndices3 )); - ServerConfig::loadMnemonicWordLists(); + } TEST_F(PassphraseTest, detectMnemonic) { diff --git a/src/cpp/test/main.cpp b/src/cpp/test/main.cpp index 1d6182b7f..5fcab4163 100644 --- a/src/cpp/test/main.cpp +++ b/src/cpp/test/main.cpp @@ -3,6 +3,12 @@ #include #include "gtest/gtest.h" +#include "Poco/Util/PropertyFileConfiguration.h" +#include "Poco/Environment.h" + +#include "../SingletonManager/ConnectionManager.h" + + std::list gTests; void fillTests() @@ -16,6 +22,39 @@ void fillTests() int load() { // init server config, init seed array + + Poco::AutoPtr test_config(new Poco::Util::LayeredConfiguration); + auto cfg = new Poco::Util::PropertyFileConfiguration("Gradido_LoginServer_Test.properties"); + test_config->add(cfg); + + if (!ServerConfig::initServerCrypto(*test_config)) { + //printf("[Gradido_LoginServer::%s] error init server crypto\n", __FUNCTION__); + printf("[load] error init server crypto"); + return -1; + } + if (!ServerConfig::loadMnemonicWordLists()) { + printf("[load] error in loadMnemonicWordLists"); + 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::iterator it = gTests.begin(); it != gTests.end(); it++) { diff --git a/src/cpsp/adminUserPasswordReset.cpsp b/src/cpsp/adminUserPasswordReset.cpsp index 8b4b09b0b..648a18f61 100644 --- a/src/cpsp/adminUserPasswordReset.cpsp +++ b/src/cpsp/adminUserPasswordReset.cpsp @@ -89,7 +89,7 @@ enum PageState
  • <%= userModel->getEmail() %>
  • Public Key: <%= userModel->getPublicKeyHex() %>
  • E-Mail überprüft: <%= std::to_string(userModel->isEmailChecked()) %>
  • -
  • Private Key verschlüsselt: <%= std::to_string(userModel->existPrivateKeyCrypted()) %>
  • +
  • Private Key verschlüsselt: <%= std::to_string(userModel->hasPrivateKeyEncrypted()) %>
  • Passwort gesetzt: <%= std::to_string(userModel->getPasswordHashed() != 0) %>
  • <% } %> diff --git a/src/cpsp/login.cpsp b/src/cpsp/login.cpsp index b93b79464..c32381745 100644 --- a/src/cpsp/login.cpsp +++ b/src/cpsp/login.cpsp @@ -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"); diff --git a/src/cpsp/registerDirect.cpsp b/src/cpsp/registerDirect.cpsp index 31d06d9fb..ac8ddab35 100644 --- a/src/cpsp/registerDirect.cpsp +++ b/src/cpsp/registerDirect.cpsp @@ -25,7 +25,7 @@ response.addCookie(session->getLoginCookie()); } - userReturned = session->createUser( + userReturned = session->createUserDirect( form.get("register-first-name", ""), form.get("register-last-name", ""), form.get("register-email", ""),