mirror of
https://github.com/IT4Change/gradido.git
synced 2025-12-13 07:45:54 +00:00
Merge branch 'master' of ssh://**REDACTED**/~/_C++/gradido_login_server
This commit is contained in:
commit
3d071f3517
@ -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})
|
||||
|
||||
@ -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<std::shared_mutex> _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<std::shared_mutex> _lock(mWorkingMutex);
|
||||
@ -128,6 +128,34 @@ AuthenticatedEncryption::ResultType AuthenticatedEncryption::decrypt(const Memor
|
||||
return AUTH_DECRYPT_OK;
|
||||
}
|
||||
|
||||
AuthenticatedEncryption::ResultType AuthenticatedEncryption::decrypt(const std::vector<unsigned char>& encryptedMessage, MemoryBin** message) const
|
||||
{
|
||||
assert(message);
|
||||
std::shared_lock<std::shared_mutex> _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) {
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
#include "../SingletonManager/MemoryManager.h"
|
||||
|
||||
#include <shared_mutex>
|
||||
#include <vector>
|
||||
|
||||
/*!
|
||||
*
|
||||
@ -46,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; }
|
||||
|
||||
@ -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<unsigned char>& 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
|
||||
@ -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 ;
|
||||
|
||||
|
||||
};
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@ -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();
|
||||
|
||||
|
||||
|
||||
@ -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> Passphrase::create(const Poco::UInt16 wordIndices[PHRA
|
||||
clearPassphrase += word;
|
||||
clearPassphrase += " ";
|
||||
}
|
||||
else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
return new Passphrase(clearPassphrase, wordSource);
|
||||
}
|
||||
|
||||
Poco::AutoPtr<Passphrase> 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()
|
||||
{
|
||||
|
||||
@ -16,6 +16,8 @@ public:
|
||||
|
||||
static Poco::AutoPtr<Passphrase> create(const Poco::UInt16 wordIndices[PHRASE_WORD_COUNT], const Mnemonic* wordSource);
|
||||
static Poco::AutoPtr<Passphrase> create(const MemoryBin* wordIndices, const Mnemonic* wordSource);
|
||||
//! \brief generate new passphrase with random
|
||||
static Poco::AutoPtr<Passphrase> generate(const Mnemonic* wordSource);
|
||||
static const Mnemonic* detectMnemonic(const std::string& passphrase, const KeyPairEd25519* keyPair = nullptr);
|
||||
|
||||
//! \brief transform passphrase into another language/mnemonic source
|
||||
|
||||
@ -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<std::shared_mutex> _lock(mWorkingMutex);
|
||||
|
||||
if (index < 2048 && index >= 0) {
|
||||
std::string word;
|
||||
{
|
||||
std::shared_lock<std::shared_mutex> _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<std::shared_mutex> _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<std::shared_mutex> _lock(mWorkingMutex);
|
||||
return mWords[index];
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void Mnemonic::clear()
|
||||
{
|
||||
//Poco::Mutex::ScopedLock _lock(mWorkingMutex, 500);
|
||||
|
||||
@ -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<std::shared_mutex> _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<std::shared_mutex> _lock(mWorkingMutex);
|
||||
|
||||
@ -207,7 +207,7 @@ void AdminUserPasswordReset::handleRequest(Poco::Net::HTTPServerRequest& request
|
||||
responseStream << "</li>\n";
|
||||
responseStream << "\t\t\t<li>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 << "</li>\n";
|
||||
responseStream << "\t\t\t<li>Passwort gesetzt: ";
|
||||
#line 93 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminUserPasswordReset.cpsp"
|
||||
|
||||
@ -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";
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -85,7 +85,7 @@ protected:
|
||||
Poco::Int8 getMemoryStackIndex(Poco::UInt16 size);
|
||||
|
||||
MemoryManager();
|
||||
MemoryPageStack* mMemoryPageStacks[5];
|
||||
MemoryPageStack* mMemoryPageStacks[6];
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -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<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;
|
||||
}
|
||||
|
||||
void User::setGradidoKeyPair(KeyPairEd25519* gradidoKeyPair)
|
||||
{
|
||||
assert(gradidoKeyPair);
|
||||
std::unique_lock<std::shared_mutex> _lock(mSharedMutex);
|
||||
if (mGradidoKeyPair) delete mGradidoKeyPair;
|
||||
mGradidoKeyPair = gradidoKeyPair;
|
||||
getModel()->setPublicKey(mGradidoKeyPair->getPublicKey());
|
||||
}
|
||||
|
||||
int User::setPassword(AuthenticatedEncryption* passwd)
|
||||
{
|
||||
std::unique_lock<std::shared_mutex> _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;
|
||||
}
|
||||
|
||||
}
|
||||
@ -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 <shared_mutex>
|
||||
|
||||
#include "TableControllerBase.h"
|
||||
|
||||
@ -34,17 +37,52 @@ namespace controller {
|
||||
inline Poco::AutoPtr<model::table::User> getModel() { return _getModel<model::table::User>(); }
|
||||
inline const model::table::User* getModel() const { return _getModel<model::table::User>(); }
|
||||
|
||||
|
||||
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<std::shared_mutex> _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<std::shared_mutex> _lock(mSharedMutex);
|
||||
return mGradidoKeyPair;
|
||||
}
|
||||
protected:
|
||||
User(model::table::User* dbModel);
|
||||
|
||||
|
||||
|
||||
std::string mPublicHex;
|
||||
|
||||
AuthenticatedEncryption* mPassword;
|
||||
KeyPairEd25519* mGradidoKeyPair;
|
||||
|
||||
mutable std::shared_mutex mSharedMutex;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -426,8 +426,8 @@ User::User(Poco::AutoPtr<controller::User> 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());
|
||||
}
|
||||
|
||||
@ -35,6 +35,7 @@ enum UserStates
|
||||
USER_EMAIL_NOT_ACTIVATED,
|
||||
USER_NO_KEYS,
|
||||
USER_NO_PRIVATE_KEY,
|
||||
USER_KEYS_DONT_MATCH,
|
||||
USER_COMPLETE
|
||||
};
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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<unsigned char>& getPrivateKeyCrypted() const { return mPrivateKey.value().content(); }
|
||||
inline bool hasPrivateKeyEncrypted() const { return !mPrivateKey.isNull(); }
|
||||
inline const std::vector<unsigned char>& 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; }
|
||||
|
||||
39
src/cpp/tasks/AuthenticatedEncryptionCreateKeyTask.cpp
Normal file
39
src/cpp/tasks/AuthenticatedEncryptionCreateKeyTask.cpp
Normal file
@ -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<controller::User> 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;
|
||||
}
|
||||
20
src/cpp/tasks/AuthenticatedEncryptionCreateKeyTask.h
Normal file
20
src/cpp/tasks/AuthenticatedEncryptionCreateKeyTask.h
Normal file
@ -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<controller::User> user, const std::string& passwd);
|
||||
virtual ~AuthenticatedEncryptionCreateKeyTask();
|
||||
|
||||
int run();
|
||||
const char* getResourceType() const { return "AuthenticatedEncryptionCreateKeyTask"; };
|
||||
protected:
|
||||
Poco::AutoPtr<controller::User> mUser;
|
||||
std::string mPassword;
|
||||
};
|
||||
|
||||
#endif //__GRADIDO_LOGIN_SERVER_TASKS_AUTHENTICATED_ENCRYPTION_CREATE_KEY_TASK_H
|
||||
10
src/cpp/test/controller/TestUser.cpp
Normal file
10
src/cpp/test/controller/TestUser.cpp
Normal file
@ -0,0 +1,10 @@
|
||||
#include "TestUser.h"
|
||||
|
||||
namespace controller {
|
||||
void TestUser::SetUp()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//TEST_F(TestUser, )
|
||||
}
|
||||
16
src/cpp/test/controller/TestUser.h
Normal file
16
src/cpp/test/controller/TestUser.h
Normal file
@ -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
|
||||
@ -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) {
|
||||
|
||||
@ -84,7 +84,7 @@ void PassphraseTest::SetUp()
|
||||
wordIndices3
|
||||
));
|
||||
|
||||
ServerConfig::loadMnemonicWordLists();
|
||||
|
||||
}
|
||||
|
||||
TEST_F(PassphraseTest, detectMnemonic) {
|
||||
|
||||
@ -3,6 +3,12 @@
|
||||
#include <list>
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "Poco/Util/PropertyFileConfiguration.h"
|
||||
#include "Poco/Environment.h"
|
||||
|
||||
#include "../SingletonManager/ConnectionManager.h"
|
||||
|
||||
|
||||
std::list<Test*> gTests;
|
||||
|
||||
void fillTests()
|
||||
@ -16,6 +22,39 @@ void fillTests()
|
||||
|
||||
int load() {
|
||||
// init server config, init seed array
|
||||
|
||||
Poco::AutoPtr<Poco::Util::LayeredConfiguration> 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<Test*>::iterator it = gTests.begin(); it != gTests.end(); it++)
|
||||
{
|
||||
|
||||
@ -89,7 +89,7 @@ enum PageState
|
||||
<li><%= userModel->getEmail() %></li>
|
||||
<li>Public Key: <%= userModel->getPublicKeyHex() %></li>
|
||||
<li>E-Mail überprüft: <%= std::to_string(userModel->isEmailChecked()) %></li>
|
||||
<li>Private Key verschlüsselt: <%= std::to_string(userModel->existPrivateKeyCrypted()) %></li>
|
||||
<li>Private Key verschlüsselt: <%= std::to_string(userModel->hasPrivateKeyEncrypted()) %></li>
|
||||
<li>Passwort gesetzt: <%= std::to_string(userModel->getPasswordHashed() != 0) %></li>
|
||||
</ul>
|
||||
<% } %>
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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", ""),
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user