From f7744ee2c15cbe03a8a5d9100e93f7e7d4fc94f7 Mon Sep 17 00:00:00 2001 From: Dario Date: Thu, 26 Sep 2019 11:26:39 +0200 Subject: [PATCH] adding many new files, mostly from old projects, register handling with validation, loading and connect to mysql --- CMakeLists.txt | 25 +- conanfile.txt | 2 + src/cpp/Crypto/KeyPair.cpp | 91 ++++ src/cpp/Crypto/KeyPair.h | 27 ++ src/cpp/Crypto/Obfus_array.cpp | 28 ++ src/cpp/Crypto/Obfus_array.h | 26 ++ src/cpp/Crypto/mnemonic.h | 1 + src/cpp/Gradido_LoginServer.cpp | 22 + src/cpp/HTTPInterface/HandleFileRequest.cpp | 9 +- src/cpp/ServerConfig.cpp | 32 +- src/cpp/ServerConfig.h | 14 + .../SingletonManager/ConnectionManager.cpp | 424 ++---------------- src/cpp/SingletonManager/ConnectionManager.h | 121 ++--- src/cpp/SingletonManager/ErrorManager.h | 4 +- src/cpp/SingletonManager/SessionManager.cpp | 68 ++- src/cpp/SingletonManager/SessionManager.h | 33 +- src/cpp/model/Error.cpp | 14 + src/cpp/model/Error.h | 2 + src/cpp/model/ErrorList.cpp | 16 + src/cpp/model/ErrorList.h | 1 + src/cpp/model/Session.cpp | 36 ++ src/cpp/model/Session.h | 9 +- src/cpp/model/User.cpp | 135 ++++++ src/cpp/model/User.h | 72 +++ src/cpsp/login.cpsp | 4 +- src/cpsp/register.cpsp | 45 +- 26 files changed, 760 insertions(+), 501 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 78c36c23d..a14419955 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,19 +8,28 @@ include_directories( "dependencies" "dependencies/tinf/src/" "dependencies/iroha-ed25519/include" + #"dependencies/mariadb-connector-c/build/include" + #"dependencies/mariadb-connector-c/include" + "import/mariadb/include" ) FILE(GLOB TINF "dependencies/tinf/src/*.c" "dependencies/tinf/src/*.h") FILE(GLOB HTTPInterface "src/cpp/HTTPInterface/*.h" "src/cpp/HTTPInterface/*.cpp") +FILE(GLOB SINGLETON_MANAGER "src/cpp/SingletonManager/*.h" "src/cpp/SingletonManager/*.cpp") +FILE(GLOB MODEL "src/cpp/model/*.h" "src/cpp/model/*.cpp") FILE(GLOB CRYPTO "src/cpp/Crypto/*.h" "src/cpp/Crypto/*.cpp") FILE(GLOB MAIN "src/cpp/*.cpp" "src/cpp/*.c" "src/cpp/*.h") -SET(LOCAL_SRCS ${TINF} ${MAIN} ${HTTPInterface} ${CRYPTO}) +FILE(GLOB MYSQL "src/cpp/MySQL/*.cpp" "src/cpp/MySQL/Poco/*.h") +SET(LOCAL_SRCS ${TINF} ${MAIN} ${HTTPInterface} ${CRYPTO} ${MODEL} ${SINGLETON_MANAGER} ${MYSQL}) aux_source_directory("src/cpp" LOCAL_SRCS) if(MSVC) # src source_group("tinf" FILES ${TINF}) source_group("crypto" FILES ${CRYPTO}) +source_group("model" FILES ${MODEL}) +source_group("mysql" FILES ${MYSQL}) +source_group("SingletonManager" FILES ${SINGLETON_MANAGER}) source_group("HTTP-Interface" FILES ${HTTPInterface}) endif(MSVC) @@ -28,16 +37,28 @@ endif(MSVC) include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) conan_basic_setup() +#add_subdirectory("dependencies/curl") +#add_subdirectory("dependencies/mariadb-connector-c") add_executable(Gradido_LoginServer ${LOCAL_SRCS}) if(WIN32) +find_library(MYSQL_LIBRARIES mariadbclient.lib PATHS "import/mariadb/lib/release") +#find_library(MYSQL_LIBRARIES_DEBUG mariadbclient.lib PATHS "import/mariadb/lib/debug") +find_library(MARIADB_CLIENT_DEBUG mariadbclient PATHS "dependencies/mariadb-connector-c/build/libmariadb/Debug" REQUIRED) find_library(IROHA_ED25519 ed25519 PATHS "dependencies/iroha-ed25519/build/Debug" REQUIRED) +set(MYSQL_INCLUDE_DIR "import/mariadb/include") else(WIN32) endif(WIN32) -target_link_libraries(Gradido_LoginServer ${CONAN_LIBS} ${IROHA_ED25519}) \ No newline at end of file + +target_link_libraries(Gradido_LoginServer ${CONAN_LIBS} ${IROHA_ED25519} ${MARIADB_CLIENT}) +if(WIN32) +TARGET_LINK_LIBRARIES(Gradido_LoginServer optimized ${MYSQL_LIBRARIES} Shlwapi) +TARGET_LINK_LIBRARIES(Gradido_LoginServer debug ${MARIADB_CLIENT_DEBUG} Shlwapi) +else(WIN32) +endif(WIN32) \ No newline at end of file diff --git a/conanfile.txt b/conanfile.txt index 6ff2f4318..9378c4a10 100644 --- a/conanfile.txt +++ b/conanfile.txt @@ -6,3 +6,5 @@ protobuf/3.9.1@bincrafters/stable [generators] cmake + + diff --git a/src/cpp/Crypto/KeyPair.cpp b/src/cpp/Crypto/KeyPair.cpp index e69de29bb..82dc46286 100644 --- a/src/cpp/Crypto/KeyPair.cpp +++ b/src/cpp/Crypto/KeyPair.cpp @@ -0,0 +1,91 @@ +#include "KeyPair.h" + +#include +#include + + +#define STR_BUFFER_SIZE 25 + +KeyPair::KeyPair() + : mPrivateKey(nullptr), mSodiumSecret(nullptr) +{ + +} + +KeyPair::~KeyPair() +{ + if (mPrivateKey) { + delete mPrivateKey; + } + if (mSodiumSecret) { + delete mSodiumSecret; + } +} + +bool KeyPair::generateFromPassphrase(const char* passphrase, Mnemonic* word_source) +{ + + // libsodium doc: https://libsodium.gitbook.io/doc/advanced/hmac-sha2 + // https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki + //crypto_auth_hmacsha512_keygen + unsigned long word_indices[PHRASE_WORD_COUNT]; + + //DHASH key = DRMakeStringHash(passphrase); + size_t pass_phrase_size = strlen(passphrase); + char acBuffer[STR_BUFFER_SIZE]; memset(acBuffer, 0, STR_BUFFER_SIZE); + size_t buffer_cursor = 0; + // get word indices for hmac key + unsigned char word_cursor = 0; + for (size_t i = 0; i < pass_phrase_size; i++) { + if (passphrase[i] == ' ') { + word_indices[word_cursor] = word_source->getWordIndex(acBuffer); + + word_cursor++; + memset(acBuffer, 0, STR_BUFFER_SIZE); + buffer_cursor = 0; + } + else { + acBuffer[buffer_cursor++] = passphrase[i]; + } + + } + sha_context state; + + unsigned char hash[SHA_512_SIZE]; + //crypto_auth_hmacsha512_state state; + size_t word_index_size = sizeof(word_indices); + //crypto_auth_hmacsha512_init(&state, (unsigned char*)word_indices, sizeof(word_indices)); + sha512_init(&state); + sha512_update(&state, (unsigned char*)word_indices, sizeof(word_indices)); + sha512_update(&state, (unsigned char*)passphrase, pass_phrase_size); + //crypto_auth_hmacsha512_update(&state, (unsigned char*)passphrase, pass_phrase_size); + sha512_final(&state, hash); + //crypto_auth_hmacsha512_final(&state, hash); + + + //ed25519_create_keypair(public_key, private_key, hash); + private_key_t prv_key_t; + memcpy(prv_key_t.data, hash, 32); + public_key_t pbl_key_t; + ed25519_derive_public_key(&prv_key_t, &pbl_key_t); + + + //memcpy(private_key, prv_key_t.data, 32); + if (mPrivateKey) { + delete mPrivateKey; + } + mPrivateKey = new ObfusArray(ed25519_privkey_SIZE, prv_key_t.data); + memcpy(mPublicKey, pbl_key_t.data, ed25519_pubkey_SIZE); + + unsigned char sodium_secret[crypto_sign_SECRETKEYBYTES]; + + crypto_sign_seed_keypair(mSodiumPublic, sodium_secret, *mPrivateKey); + + if(mSodiumSecret) { + delete mSodiumSecret; + } + mSodiumSecret = new ObfusArray(crypto_sign_SECRETKEYBYTES, sodium_secret); + + // using + return true; +} \ No newline at end of file diff --git a/src/cpp/Crypto/KeyPair.h b/src/cpp/Crypto/KeyPair.h index e69de29bb..f294e9b05 100644 --- a/src/cpp/Crypto/KeyPair.h +++ b/src/cpp/Crypto/KeyPair.h @@ -0,0 +1,27 @@ +#ifndef GRADIDO_LOGIN_SERVER_CRYPTO_KEY_PAIR +#define GRADIDO_LOGIN_SERVER_CRYPTO_KEY_PAIR + +#include "Obfus_array.h" +#include "mnemonic.h" + +#include "ed25519/ed25519.h" +#include + +class KeyPair +{ +public: + KeyPair(); + ~KeyPair(); + + bool generateFromPassphrase(const char* passphrase, Mnemonic* word_source); + +protected: + +private: + ObfusArray* mPrivateKey; + ObfusArray* mSodiumSecret; + unsigned char mPublicKey[ed25519_pubkey_SIZE]; + unsigned char mSodiumPublic[crypto_sign_PUBLICKEYBYTES]; +}; + +#endif //GRADIDO_LOGIN_SERVER_CRYPTO_KEY_PAIR \ No newline at end of file diff --git a/src/cpp/Crypto/Obfus_array.cpp b/src/cpp/Crypto/Obfus_array.cpp index e69de29bb..101df0c84 100644 --- a/src/cpp/Crypto/Obfus_array.cpp +++ b/src/cpp/Crypto/Obfus_array.cpp @@ -0,0 +1,28 @@ +#include "Obfus_array.h" +#include +#include +#include + +ObfusArray::ObfusArray(size_t size, const unsigned char * data) + : m_arraySize(0), m_offsetSize(0), m_dataSize(size), m_Data(nullptr) +{ + m_arraySize = randombytes_random() % (int)roundf(size + size*0.25f); + m_Data = (unsigned char*)malloc(m_arraySize); + m_offsetSize = randombytes_random() % (int)roundf((m_arraySize - m_dataSize) * 0.8f); + + for (size_t i = 0; i < (size_t)floorf(m_arraySize / 4.0f); i++) { + uint32_t* d = (uint32_t*)m_Data[i]; + *d = randombytes_random(); + } + uint32_t* d = (uint32_t*)(m_Data + (m_arraySize - 4)); + *d = randombytes_random(); + + memcpy(&m_Data[m_offsetSize], data, size); +} + +ObfusArray::~ObfusArray() +{ + if (m_Data) { + free(m_Data); + } +} \ No newline at end of file diff --git a/src/cpp/Crypto/Obfus_array.h b/src/cpp/Crypto/Obfus_array.h index e69de29bb..b8f447941 100644 --- a/src/cpp/Crypto/Obfus_array.h +++ b/src/cpp/Crypto/Obfus_array.h @@ -0,0 +1,26 @@ +#ifndef GRADIDO_LOGIN_SERVER_CRYPTO_OBFUS_ARRAY +#define GRADIDO_LOGIN_SERVER_CRYPTO_OBFUS_ARRAY + + + +class ObfusArray +{ +public: + ObfusArray(size_t size, const unsigned char * data); + ~ObfusArray(); + + operator const unsigned char*() { + return &m_Data[m_offsetSize]; + } + size_t size() { + return m_dataSize; + } + +private: + size_t m_arraySize; + size_t m_offsetSize; + size_t m_dataSize; + unsigned char* m_Data; +}; + +#endif //GRADIDO_LOGIN_SERVER_CRYPTO_OBFUS_ARRAY \ No newline at end of file diff --git a/src/cpp/Crypto/mnemonic.h b/src/cpp/Crypto/mnemonic.h index 3997e8cee..43ee477d4 100644 --- a/src/cpp/Crypto/mnemonic.h +++ b/src/cpp/Crypto/mnemonic.h @@ -13,6 +13,7 @@ #include "DRHashList.h" +#define PHRASE_WORD_COUNT 24 class Mnemonic diff --git a/src/cpp/Gradido_LoginServer.cpp b/src/cpp/Gradido_LoginServer.cpp index b4b769249..41bae4e8f 100644 --- a/src/cpp/Gradido_LoginServer.cpp +++ b/src/cpp/Gradido_LoginServer.cpp @@ -1,9 +1,15 @@ #include "Gradido_LoginServer.h" +#include "ServerConfig.h" #include "HTTPInterface/PageRequestHandlerFactory.h" + +#include "SingletonManager/ConnectionManager.h" +#include "SingletonManager/SessionManager.h" + #include "Poco/Util/HelpFormatter.h" #include "Poco/Net/ServerSocket.h" #include "Poco/Net/HTTPServer.h" +#include "MySQL/Poco/Connector.h" #include @@ -65,6 +71,22 @@ int Gradido_LoginServer::main(const std::vector& args) { unsigned short port = (unsigned short)config().getInt("HTTPServer.port", 9980); + // load word lists + ServerConfig::loadMnemonicWordLists(); + + // load up connection configs + // register MySQL connector + Poco::Data::MySQL::Connector::registerConnector(); + //Poco::Data::MySQL::Connector::KEY; + auto conn = ConnectionManager::getInstance(); + //conn->setConnection() + conn->setConnectionsFromConfig(config(), CONNECTION_MYSQL_LOGIN_SERVER); + conn->setConnectionsFromConfig(config(), CONNECTION_MYSQL_PHP_SERVER); + + SessionManager::getInstance()->init(); + // put urandom on linux servers + //srand(); + // set-up a server socket Poco::Net::ServerSocket svs(port); // set-up a HTTPServer instance diff --git a/src/cpp/HTTPInterface/HandleFileRequest.cpp b/src/cpp/HTTPInterface/HandleFileRequest.cpp index bc1138f98..3b6b049e8 100644 --- a/src/cpp/HTTPInterface/HandleFileRequest.cpp +++ b/src/cpp/HTTPInterface/HandleFileRequest.cpp @@ -27,7 +27,14 @@ void HandleFileRequest::handleRequest(Poco::Net::HTTPServerRequest& request, Poc } std::string path = "data" + uri; printf("file path: %s\n", path.data()); - response.sendFile(path, mediaType); + try { + response.sendFile(path, mediaType); + } + catch (...) { + std::ostream& _responseStream = response.send(); + _responseStream << "Error, file not found"; + + } /* bool _compressResponse(request.hasToken("Accept-Encoding", "gzip")); if (_compressResponse) response.set("Content-Encoding", "gzip"); diff --git a/src/cpp/ServerConfig.cpp b/src/cpp/ServerConfig.cpp index 25983c664..8b4eb835a 100644 --- a/src/cpp/ServerConfig.cpp +++ b/src/cpp/ServerConfig.cpp @@ -1 +1,31 @@ -#include "ServerConfig.h" \ No newline at end of file +#include "ServerConfig.h" +#include "Crypto/mnemonic_german.h" +#include "Crypto/mnemonic_bip0039.h" + +namespace ServerConfig { + Mnemonic g_Mnemonic_WordLists[MNEMONIC_MAX]; + + void loadMnemonicWordLists() + { + for (int i = 0; i < MNEMONIC_MAX; i++) { + int iResult = 0; + switch (i) { + case MNEMONIC_GRADIDO_BOOK_GERMAN_RANDOM_ORDER: + iResult = g_Mnemonic_WordLists[i].init(populate_mnemonic_german, g_mnemonic_german_original_size, g_mnemonic_german_compressed_size); + if (iResult) { + printf("[%s] error init german mnemonic set, error nr: %d\n", __FUNCTION__, iResult); + //return -1; + } + break; + case MNEMONIC_BIP0039_SORTED_ORDER: + iResult = g_Mnemonic_WordLists[i].init(populate_mnemonic_bip0039, g_mnemonic_bip0039_original_size, g_mnemonic_bip0039_compressed_size); + if (iResult) { + printf("[%s] error init bip0039 mnemonic set, error nr: %d\n", __FUNCTION__, iResult); + + } + break; + default: printf("[%s] unknown MnemonicType\n", __FUNCTION__); + } + } + } +} \ No newline at end of file diff --git a/src/cpp/ServerConfig.h b/src/cpp/ServerConfig.h index e69de29bb..845f7ab4a 100644 --- a/src/cpp/ServerConfig.h +++ b/src/cpp/ServerConfig.h @@ -0,0 +1,14 @@ +#include "Crypto/mnemonic.h" + +namespace ServerConfig { + + enum Mnemonic_Types { + MNEMONIC_GRADIDO_BOOK_GERMAN_RANDOM_ORDER, + MNEMONIC_BIP0039_SORTED_ORDER, + MNEMONIC_MAX + }; + + extern Mnemonic g_Mnemonic_WordLists[MNEMONIC_MAX]; + + void loadMnemonicWordLists(); +} \ No newline at end of file diff --git a/src/cpp/SingletonManager/ConnectionManager.cpp b/src/cpp/SingletonManager/ConnectionManager.cpp index 7d7c9f458..e45013404 100644 --- a/src/cpp/SingletonManager/ConnectionManager.cpp +++ b/src/cpp/SingletonManager/ConnectionManager.cpp @@ -1,405 +1,65 @@ #include "ConnectionManager.h" -#include "../Connections/MysqlConnection.h" #include - -ConnectThread::ConnectThread(ConnectionManager* parent) - : Thread(true), initMysqlThread(false), mParent(parent) -{ - -} - -ConnectThread::~ConnectThread() -{ - -} - -int ConnectThread::ThreadFunction() -{ - if (!initMysqlThread) { - if(mysql_thread_init()) { - printf("error by calling mysql thread init\n"); - } - initMysqlThread = true; - } - mDataMutex.lock(); - - // clean up not longer used connections - while (mConnectionWaitingOnDestroy.size() > 0) { - auto con = mConnectionWaitingOnDestroy.front(); - mConnectionWaitingOnDestroy.pop(); - mDataMutex.unlock(); - delete con; - mDataMutex.lock(); - } - - // creating new connections - while(mConnectionsWaitingOnConnectCall.size() > 0) { - auto con = mConnectionsWaitingOnConnectCall.front(); - mConnectionsWaitingOnConnectCall.pop(); - mDataMutex.unlock(); - if(!con->connect()) { - //printf("[ConnectThread::ThreadFunction] error connecting with type: %s\n", - //Connection::getConnectionTypeName(con->getType())); - }; - mParent->markAsAvailable(con); - mParent->condSignal(); - mDataMutex.lock(); - } - mDataMutex.unlock(); - - return 0; -} - -void ConnectThread::cleanUpInThread() -{ - if (initMysqlThread) { - mysql_thread_end(); - initMysqlThread = false; - } -} - -void ConnectThread::addConnectionConnect(Connection* connection) -{ - mDataMutex.lock(); - mConnectionsWaitingOnConnectCall.push(connection); - mDataMutex.unlock(); -} - - -void ConnectThread::addConnectionDestroy(Connection* connection) -{ - mDataMutex.lock(); - mConnectionWaitingOnDestroy.push(connection); - mDataMutex.unlock(); -} - -// ----------------------------------------------------------------- -// ConnectionManager -// ----------------------------------------------------------------- - ConnectionManager* ConnectionManager::getInstance() { static ConnectionManager only; return &only; } + ConnectionManager::ConnectionManager() - : mConnectionEstablishThread(this), mInitalized(true) { } ConnectionManager::~ConnectionManager() { - if (mInitalized) { - deinitalize(); - } + } -void ConnectionManager::deinitalize() +bool ConnectionManager::setConnectionsFromConfig(const Poco::Util::LayeredConfiguration& config, ConnectionType type) { - lock(); - mInitalized = false; - unlock(); - - mConnectionEstablishThread.exitThread(); - - for (auto it = mConnections.begin(); it != mConnections.end(); it++) - { - auto freeConnections = it->second->mFreeConnections; - while (freeConnections.size() > 0) { - delete freeConnections.top(); - freeConnections.pop(); - } - auto cfg_ptr = it->second->cfg_ptr; - cfg_ptr->removeRef(); - if (cfg_ptr->getRef() <= 0) { - delete cfg_ptr; - } - } - mConnections.clear(); - mInitalized = false; - -} - -bool ConnectionManager::addConnectionPool(DRSimpleResourcePtr* cfg_ptr) -{ - if (!mInitalized) { - printf("[ConnectionManager::%s] not initialized any more\n", __FUNCTION__); - return false; - } - if ((*cfg_ptr)->name == std::string("")) { - // getConnectionTypeName - ConnectionConfig* cfg = static_cast((Config*)(*cfg_ptr)); - (*cfg_ptr)->name = "Connect_"; - (*cfg_ptr)->name += Connection::getConnectionTypeName(cfg->type); - if (cfg->type == CONN_MYSQL) { - DBConnectionConfig* db_cfg = static_cast((Config*)(*cfg_ptr)); - (*cfg_ptr)->name += "_"; - (*cfg_ptr)->name += db_cfg->db; - } - } - - DHASH id = (*cfg_ptr)->getHash(); - - // check if collision - lock(); - if (!mInitalized) { - printf("[ConnectionManager::%s] not initialized any more\n", __FUNCTION__); - return false; - } - - auto it = mConnections.find(id); - if (it != mConnections.end()) { - unlock(); - if ((*it->second->cfg_ptr)->name == (*cfg_ptr)->name) { - printf("connection %s already in there: %s\n", (*cfg_ptr)->name.data(), __FUNCTION__); - return false; - } - else { - printf("Hash Collision detected with %s and %s in %s\n", - (*cfg_ptr)->name.data(), (*it->second->cfg_ptr)->name.data(), __FUNCTION__); - return false; - } - } - unlock(); - // try to create connection object - - auto con = createConnection(cfg_ptr); - if (!con) { - printf("couldn't create connection with cfg: %s\n", (*cfg_ptr)->name.data()); - return false; - } - // create pool - auto pool = new ConnectionPool; - //pool->cfg = cfg; - pool->cfg_ptr = cfg_ptr; - pool->cfg_ptr->addRef(); - printf("create new connection pool for connection: %s\n", (*cfg_ptr)->name.data()); - - lock(); - if (!mInitalized) { - printf("[ConnectionManager::%s] not initialized any more\n", __FUNCTION__); - return false; - } - - mConnections.insert(std::pair(id, pool)); - - unlock(); - - // start connection - if(con) { - mConnectionEstablishThread.addConnectionConnect(con); - mConnectionEstablishThread.condSignal(); - } - - - return true; -} - -bool ConnectionManager::markAsAvailable(Connection* con) -{ - if (!mInitalized) { - addError(new Error(__FUNCTION__, "not initialized any more")); - return false; - } - - DHASH id = con->getHash(); - lock(); - if (!mInitalized) { - addError(new Error(__FUNCTION__, "not initialized any more")); - return false; - } - - auto it = mConnections.find(id); - if (it == mConnections.end()) { - addError(new ParamError(__FUNCTION__, "couldn't find connection pool for id:", id)); - delete con; - unlock(); - return false; - } - else if (!con->isOpen()) { - if (con->errorCount() > 0) { - it->second->mErrorConnectingAttempts++; - addError(new ParamError(__FUNCTION__, "connection wasn't open and has errors, failed connecting attempt: ", it->second->mErrorConnectingAttempts)); - getErrors(con); - unlock(); - return false; - } - } - it->second->mFreeConnections.push(con); - checkTime(it->second); - - unlock(); - return true; -} - -void ConnectionManager::checkTime(ConnectionPool* pool) -{ - if (!mInitalized) { - addError(new Error(__FUNCTION__, "not initialized any more")); - return; - } - - auto currentSize = pool->mFreeConnections.size(); - // (re)start timer if at least three unused connections reached - if (pool->mFreeConnectionsCount < 3 && currentSize >= 3) { - pool->mConnectionFreeTimeout.reset(); - } - if (currentSize >= 3 && pool->mConnectionFreeTimeout.seconds() > UNUSED_CONNECTION_TIMEOUT_SECONDS) { - // clean one connection and reset timer - auto con = pool->mFreeConnections.top(); - pool->mFreeConnections.pop(); - currentSize = pool->mFreeConnections.size(); - - mConnectionEstablishThread.addConnectionDestroy(con); - mConnectionEstablishThread.condSignal(); - pool->mConnectionFreeTimeout.reset(); - - } - pool->mFreeConnectionsCount = currentSize; -} - -Connection* ConnectionManager::createConnection(DRSimpleResourcePtr* cfg_ptr) -{ - - auto con_cfg = static_cast((Config*)(*cfg_ptr)); - switch (con_cfg->type) { - case CONN_DEFAULT: return new Connection(cfg_ptr); - case CONN_MYSQL: return new MysqlConnection(cfg_ptr); - } - return nullptr; -} - -bool ConnectionManager::isConnectionPool(DHASH id) -{ - if (!mInitalized) { - addError(new Error(__FUNCTION__, "not initialized any more")); - return false; - } - lock(); - if (!mInitalized) { - addError(new Error(__FUNCTION__, "not initialized any more")); - return false; - } - auto it = mConnections.find(id); - if (it == mConnections.end()) { - unlock(); - return false; - } - unlock(); - return true; -} - -Connection* ConnectionManager::getConnection(DHASH id) -{ - if (!mInitalized) { - addError(new Error(__FUNCTION__, "not initialized any more")); - return nullptr; - } - lock(); - if (!mInitalized) { - unlock(); - addError(new Error(__FUNCTION__, "not initialized any more")); - return nullptr; - } - auto it = mConnections.find(id); - if (it == mConnections.end()) { - addError(new ParamError(__FUNCTION__, "couldn't find connection pool for id:", id)); - unlock(); - return nullptr; - } - Connection* result = nullptr; - auto pool = it->second; - if (pool->mFreeConnections.size() > 0) { - result = pool->mFreeConnections.top(); - pool->mFreeConnections.pop(); - checkTime(pool); - } - unlock(); - // if pool is empty, create new connection - if (pool->mFreeConnections.size() == 0) { - auto con = createConnection(pool->cfg_ptr); - if (!con) { - addError(new ParamError(__FUNCTION__, "couldn't create connection with cfg:", (*pool->cfg_ptr)->name)); - return nullptr; - } - mConnectionEstablishThread.addConnectionConnect(con); - mConnectionEstablishThread.condSignal(); - } - - // we have get a connection, return - if (result) { - return result; - } - // we haven't get a connection, so we wait - std::unique_lock lk(mConnectCondMutex); - mConnectCond.wait(lk, [] {return 1; }); - lock(); - if (!mInitalized) { - unlock(); - addError(new Error(__FUNCTION__, "not initialized any more")); - return nullptr; - } - - if (pool->mFreeConnections.size() == 0) { - addError(new Error(__FUNCTION__, "no free connection after wait :/")); - unlock(); - return nullptr; - } - result = pool->mFreeConnections.top(); - pool->mFreeConnections.pop(); - checkTime(pool); - unlock(); - return result; -} - -// int ConnectionManager::connectMysql( -// const char* db, -// const char* username /* = "root"*/, -// const char* pwd /* = nullptr*/, -// const char* url /* = "127.0.0.1" */, -// int port /*= 3306*/ ) -// { - //mysqlx://mike:s3cr3t!@localhost:13009 - /*std::stringstream urlStream; - urlStream << username; - if (pwd) { - urlStream << ":" << pwd; - } - urlStream << "@" << url; - urlStream << ":" << port; - */ /* - mysqlx::Session* mysqlSession = nullptr; - try { - mysqlSession = new mysqlx::Session(url, port, username, pwd, db); - } - catch (const char* e) { - printf("[ConnectionManager::connectMysql] catch e: %s\n", e); - return -1; - } + phpServer.url = 127.0.0.1:80/gradido_php + phpServer.db.host = localhost + phpServer.db.name = cake_gradido_node + phpServer.db.user = root + phpServer.db.password = + phpServer.db.port = 3306 - mWorkingMutex.lock(); + loginServer.url = + loginServer.db.host = localhost + loginServer.db.name = gradido_login + loginServer.db.user = gradido_login + loginServer.db.password = hj2-sk28sKsj8(u_ske + loginServer.db.port = 3306 + */ - int handle = mMysqlConnections.size(); - mMysqlConnections.insert(std::pair(handle, mysqlSession)); - - return handle; - - return 0; -} -/* -mysqlx::Session* ConnectionManager::getMysqlConnection(int handle) -{ - mysqlx::Session* session = nullptr; - mWorkingMutex.lock(); - auto it = mMysqlConnections.find(handle); - if (it != mMysqlConnections.end()) { - session = it->second; + /* + connectionString example: host=localhost;port=3306;db=mydb;user=alice;password=s3cr3t;compress=true;auto-reconnect=true + */ + std::string firstKeyPart; + switch (type) { + case CONNECTION_MYSQL_LOGIN_SERVER: firstKeyPart = "loginServer"; break; + case CONNECTION_MYSQL_PHP_SERVER: firstKeyPart = "phpServer"; break; + default: addError(new Error(__FUNCTION__, "type invalid")); return false; } - mWorkingMutex.unlock(); - return session; -} -*/ + std::stringstream dbConfig; + dbConfig << "host=" << config.getString(firstKeyPart + ".db.host", "localhost") << ";"; + dbConfig << "port=" << config.getInt(firstKeyPart + ".db.port", 3306) << ";"; + std::string dbName = config.getString(firstKeyPart + ".db.name", ""); + if (dbName == "") { + addError(new Error(__FUNCTION__, "no db name given")); + return false; + } + dbConfig << "db=" << dbName << ";"; + dbConfig << "user=" << config.getString(firstKeyPart + ".db.user", "root") << ";"; + dbConfig << "password=" << config.getString(firstKeyPart + ".db.password", "") << ";"; + dbConfig << "auto-reconnect=true"; + + setConnection(dbConfig.str(), type); + + return true; + +} \ No newline at end of file diff --git a/src/cpp/SingletonManager/ConnectionManager.h b/src/cpp/SingletonManager/ConnectionManager.h index a30eb39fc..93dfdf359 100644 --- a/src/cpp/SingletonManager/ConnectionManager.h +++ b/src/cpp/SingletonManager/ConnectionManager.h @@ -1,104 +1,57 @@ -/*! -* -* \author: einhornimmond -* -* \date: 28.02.19 -* -* \brief: manage Connections like mysql or socket connections to another server -*/ +#ifndef GRADIDO_LOGIN_SERVER_SINGLETON_MANAGER_CONNECTION_MANAGER_INCLUDE +#define GRADIDO_LOGIN_SERVER_SINGLETON_MANAGER_CONNECTION_MANAGER_INCLUDE -#ifndef DR_LUA_WEB_MODULE_CONNECTION_MANAGER_H -#define DR_LUA_WEB_MODULE_CONNECTION_MANAGER_H +#include "../Crypto/DRHashList.h" +#include -#include "../LuaWebModule.h" -#include "../Connections/Connection.h" -#include "../CoreLib/Profiler.h" -#include "../CoreLib/Thread.h" -#include "../CoreLib/DRResourcePtr.h" -#include -#include +#include "Poco/Util/LayeredConfiguration.h" +#include "Poco/Data/SessionPoolContainer.h" +#include "Poco/Data/MySQL/Connector.h" -#define UNUSED_CONNECTION_TIMEOUT_SECONDS 2 +#include "../Model/ErrorList.h" -class ConnectionManager; - -class ConnectThread : public Thread -{ -public: - ConnectThread(ConnectionManager* parent); - virtual ~ConnectThread(); - - void addConnectionConnect(Connection* connection); - void addConnectionDestroy(Connection* connection); - -protected: - std::mutex mDataMutex; - std::queue mConnectionsWaitingOnConnectCall; - std::queue mConnectionWaitingOnDestroy; - - virtual int ThreadFunction(); - virtual void cleanUpInThread(); - - bool initMysqlThread; - ConnectionManager* mParent; +enum ConnectionType { + CONNECTION_MYSQL_LOGIN_SERVER, + CONNECTION_MYSQL_PHP_SERVER, + CONNECTION_MAX }; - class ConnectionManager : public ErrorList { - friend ConnectThread; - -public: +public: ~ConnectionManager(); static ConnectionManager* getInstance(); - bool addConnectionPool(DRSimpleResourcePtr* cfg); - bool markAsAvailable(Connection* con); + bool setConnectionsFromConfig(const Poco::Util::LayeredConfiguration& config, ConnectionType type); - bool isConnectionPool(DHASH id); - - static Connection* createConnection(DRSimpleResourcePtr* cfg); - inline Connection* getConnection(const char* name) { return getConnection(DRMakeStringHash(name)); } + //! \param connectionString example: host=localhost;port=3306;db=mydb;user=alice;password=s3cr3t;compress=true;auto-reconnect=true + inline void setConnection(std::string connectionString, ConnectionType type) { + if (type == CONNECTION_MYSQL_LOGIN_SERVER || CONNECTION_MYSQL_PHP_SERVER) { + mSessionPoolNames[type] = Poco::Data::Session::uri(Poco::Data::MySQL::Connector::KEY, connectionString); + mSessionPools.add(Poco::Data::MySQL::Connector::KEY, connectionString); + //mConnectionData[type] = connectionString; + } + } - Connection* getConnection(DHASH id); - - inline void lock() { mWorkingMutex.lock(); } - inline void unlock() { mWorkingMutex.unlock(); } - - void deinitalize(); + inline Poco::Data::Session getConnection(ConnectionType type) { + switch (type) + { + case CONNECTION_MYSQL_LOGIN_SERVER: + break; + case CONNECTION_MYSQL_PHP_SERVER: + break; + default: + break; + } + } protected: ConnectionManager(); - struct ConnectionPool { - ConnectionPool(): mFreeConnectionsCount(0), mErrorConnectingAttempts(0){} - DRSimpleResourcePtr* cfg_ptr; - std::stack mFreeConnections; - // used to measure how long at least two connections not used - Profiler mConnectionFreeTimeout; - // only for calculating connection timeout - int mFreeConnectionsCount; - - int mErrorConnectingAttempts; - }; - - void checkTime(ConnectionPool* pool); - - // connection Pool - std::map mConnections; - - // access mutex - std::mutex mWorkingMutex; - - inline void condSignal() { mConnectCond.notify_one(); } - - // creating and destroying connections thread - ConnectThread mConnectionEstablishThread; - std::condition_variable mConnectCond; - std::mutex mConnectCondMutex; - - bool mInitalized; +private: + std::string mSessionPoolNames[CONNECTION_MAX]; + Poco::Data::SessionPoolContainer mSessionPools; }; -#endif //DR_LUA_WEB_MODULE_CONNECTION_MANAGER_H +#endif //GRADIDO_LOGIN_SERVER_SINGLETON_MANAGER_CONNECTION_MANAGER_INCLUDE \ No newline at end of file diff --git a/src/cpp/SingletonManager/ErrorManager.h b/src/cpp/SingletonManager/ErrorManager.h index e0ad0ddd5..e9a45295f 100644 --- a/src/cpp/SingletonManager/ErrorManager.h +++ b/src/cpp/SingletonManager/ErrorManager.h @@ -15,8 +15,8 @@ #include #include #include -#include "../Error/Error.h" -#include "../CoreLib/DRHash.hpp" +#include "../Model/Error.h" +#include "../Crypto/DRHash.h" class ErrorManager : public IErrorCollection { diff --git a/src/cpp/SingletonManager/SessionManager.cpp b/src/cpp/SingletonManager/SessionManager.cpp index f91c3f865..0d185d19f 100644 --- a/src/cpp/SingletonManager/SessionManager.cpp +++ b/src/cpp/SingletonManager/SessionManager.cpp @@ -1,5 +1,8 @@ #include "SessionManager.h" +#include + + SessionManager* SessionManager::getInstance() { static SessionManager only; @@ -7,7 +10,7 @@ SessionManager* SessionManager::getInstance() } SessionManager::SessionManager() - : mInitalized(true) + : mInitalized(false) { } @@ -19,6 +22,26 @@ SessionManager::~SessionManager() } } + +bool SessionManager::init() +{ + mWorkingMutex.lock(); + for (int i = 0; i < VALIDATE_MAX; i++) { + switch (i) { + //case VALIDATE_NAME: mValidations[i] = new Poco::RegularExpression("/^[a-zA-Z_ -]{3,}$/"); break; + case VALIDATE_NAME: mValidations[i] = new Poco::RegularExpression("^[a-zA-Z]{3,}$"); break; + case VALIDATE_EMAIL: mValidations[i] = new Poco::RegularExpression("^[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$"); break; + case VALIDATE_PASSWORD: mValidations[i] = new Poco::RegularExpression("^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[@$!%*?&+-])[A-Za-z0-9@$!%*?&+-]{8,}$"); break; + case VALIDATE_PASSPHRASE: mValidations[i] = new Poco::RegularExpression("^(?:[a-z]* ){23}[a-z]*\s*$"); break; + default: printf("[SessionManager::%s] unknown validation type\n", __FUNCTION__); + } + } + + mInitalized = true; + mWorkingMutex.unlock(); + return true; +} + void SessionManager::deinitalize() { @@ -32,13 +55,26 @@ void SessionManager::deinitalize() delete it->second; } mRequestSessionMap.clear(); + + for (int i = 0; i < VALIDATE_MAX; i++) { + delete mValidations[i]; + } + mInitalized = false; mWorkingMutex.unlock(); } +bool SessionManager::isValid(const std::string& subject, SessionValidationTypes validationType) +{ + if (validationType >= VALIDATE_MAX) { + return false; + } + return *mValidations[validationType] == subject; +} -MysqlSession* SessionManager::getNewMysqlSession(int* handle) + +Session* SessionManager::getNewSession(int* handle) { if (!mInitalized) { printf("[SessionManager::%s] not initialized any more\n", __FUNCTION__); @@ -53,7 +89,7 @@ MysqlSession* SessionManager::getNewMysqlSession(int* handle) mEmptyRequestStack.pop(); auto resultIt = mRequestSessionMap.find(local_handle); if (resultIt != mRequestSessionMap.end()) { - MysqlSession* result = resultIt->second; + Session* result = resultIt->second; mWorkingMutex.unlock(); if (handle) { @@ -64,9 +100,23 @@ MysqlSession* SessionManager::getNewMysqlSession(int* handle) } else { // else create new RequestSession Object - int newHandle = mRequestSessionMap.size(); - auto requestSession = new MysqlSession(newHandle); - mRequestSessionMap.insert(std::pair(newHandle, requestSession)); + // calculate random handle + // check if already exist, if get new + int newHandle = 0; + int maxTrys = 0; + do { + newHandle = randombytes_random(); + maxTrys++; + } while (mRequestSessionMap.find(newHandle) != mRequestSessionMap.end() && maxTrys < 100); + + if (maxTrys >= 100 || 0 == newHandle) { + printf("[SessionManager::%s] can't find new handle, have already: %d", + __FUNCTION__, mRequestSessionMap.size()); + return nullptr; + } + + auto requestSession = new Session(newHandle); + mRequestSessionMap.insert(std::pair(newHandle, requestSession)); mWorkingMutex.unlock(); if (handle) { @@ -79,7 +129,7 @@ MysqlSession* SessionManager::getNewMysqlSession(int* handle) return nullptr; } -bool SessionManager::releseMysqlSession(int requestHandleSession) +bool SessionManager::releseSession(int requestHandleSession) { if (!mInitalized) { printf("[SessionManager::%s] not initialized any more\n", __FUNCTION__); @@ -115,13 +165,13 @@ bool SessionManager::isExist(int requestHandleSession) return result; } -MysqlSession* SessionManager::getMysqlSession(int handle) +Session* SessionManager::getSession(int handle) { if (!mInitalized) { printf("[SessionManager::%s] not initialized any more\n", __FUNCTION__); return nullptr; } - MysqlSession* result = nullptr; + Session* result = nullptr; mWorkingMutex.lock(); auto it = mRequestSessionMap.find(handle); if (it != mRequestSessionMap.end()) { diff --git a/src/cpp/SingletonManager/SessionManager.h b/src/cpp/SingletonManager/SessionManager.h index 4b8f63970..d2abf8cdc 100644 --- a/src/cpp/SingletonManager/SessionManager.h +++ b/src/cpp/SingletonManager/SessionManager.h @@ -11,12 +11,22 @@ #define DR_LUA_WEB_MODULE_SESSION_MANAGER_H -#include "../Session/MysqlSession.h" +#include "../Model/Session.h" + +#include "Poco/RegularExpression.h" #include #include #include +enum SessionValidationTypes { + VALIDATE_NAME, + VALIDATE_EMAIL, + VALIDATE_PASSWORD, + VALIDATE_PASSPHRASE, + VALIDATE_MAX +}; + class SessionManager { public: @@ -24,15 +34,19 @@ public: static SessionManager* getInstance(); - MysqlSession* getNewMysqlSession(int* handle = nullptr); - inline bool releseMysqlSession(MysqlSession* requestSession) { - return releseMysqlSession(requestSession->getHandle()); + Session* getNewSession(int* handle = nullptr); + inline bool releseSession(Session* requestSession) { + return releseSession(requestSession->getHandle()); } - bool releseMysqlSession(int requestHandleSession); + bool releseSession(int requestHandleSession); bool isExist(int requestHandleSession); - MysqlSession* getMysqlSession(int handle); + Session* getSession(int handle); + bool init(); void deinitalize(); + + bool isValid(const std::string& subject, SessionValidationTypes validationType); + protected: SessionManager(); @@ -41,10 +55,13 @@ protected: std::mutex mWorkingMutex; // sessions storage - std::map mRequestSessionMap; - std::stack mEmptyRequestStack; + std::map mRequestSessionMap; + std::stack mEmptyRequestStack; bool mInitalized; + + // validations + Poco::RegularExpression* mValidations[VALIDATE_MAX]; }; #endif //DR_LUA_WEB_MODULE_SESSION_MANAGER_H \ No newline at end of file diff --git a/src/cpp/model/Error.cpp b/src/cpp/model/Error.cpp index 7517fea9c..dc0fccdcc 100644 --- a/src/cpp/model/Error.cpp +++ b/src/cpp/model/Error.cpp @@ -19,11 +19,25 @@ std::string Error::getString() return ss.str(); } +std::string Error::getHtmlString() +{ + std::stringstream ss; + ss << mFunctionName << ": " << mMessage << std::endl; + + return ss.str(); +} std::string ParamError::getString() { std::stringstream ss; ss << mFunctionName << ": " << mMessage << " " << mParam << std::endl; + return ss.str(); +} +std::string ParamError::getHtmlString() +{ + std::stringstream ss; + ss << mFunctionName << ": " << mMessage << " " << mParam << std::endl; + return ss.str(); } \ No newline at end of file diff --git a/src/cpp/model/Error.h b/src/cpp/model/Error.h index aaa1e1dc0..5a23424dc 100644 --- a/src/cpp/model/Error.h +++ b/src/cpp/model/Error.h @@ -22,6 +22,7 @@ public: const char* getFunctionName() { return mFunctionName.data(); } const char* getMessage() { return mMessage.data(); } virtual std::string getString(); + virtual std::string getHtmlString(); protected: std::string mFunctionName; @@ -44,6 +45,7 @@ public: } virtual std::string getString(); + virtual std::string getHtmlString(); protected: std::string mParam; }; diff --git a/src/cpp/model/ErrorList.cpp b/src/cpp/model/ErrorList.cpp index 2bda631c5..0232e440c 100644 --- a/src/cpp/model/ErrorList.cpp +++ b/src/cpp/model/ErrorList.cpp @@ -63,4 +63,20 @@ void ErrorList::printErrors() printf(error->getString().data()); delete error; } +} + +std::string ErrorList::getErrorsHtml() +{ + std::string res; + res = "
    "; + while (mErrorStack.size() > 0) { + auto error = mErrorStack.top(); + mErrorStack.pop(); + res += "
  • "; + res += error->getHtmlString(); + res += "
  • "; + delete error; + } + res += "
"; + return res; } \ No newline at end of file diff --git a/src/cpp/model/ErrorList.h b/src/cpp/model/ErrorList.h index f88531c93..5ee7a8cd1 100644 --- a/src/cpp/model/ErrorList.h +++ b/src/cpp/model/ErrorList.h @@ -36,6 +36,7 @@ public: int getErrors(ErrorList* send); void printErrors(); + std::string getErrorsHtml(); protected: std::stack mErrorStack; diff --git a/src/cpp/model/Session.cpp b/src/cpp/model/Session.cpp index 791a8c27e..5187b009a 100644 --- a/src/cpp/model/Session.cpp +++ b/src/cpp/model/Session.cpp @@ -1,4 +1,6 @@ #include "Session.h" +#include "Poco/RegularExpression.h" +#include "../SingletonManager/SessionManager.h" Session::Session(int handle) : mHandleId(handle) @@ -11,3 +13,37 @@ Session::~Session() } + + +void Session::reset() +{ + +} + +bool Session::createUser(const std::string& name, const std::string& email, const std::string& password, const std::string& passphrase) +{ + auto sm = SessionManager::getInstance(); + if (!sm->isValid(name, VALIDATE_NAME)) { + addError(new Error("Vorname", "Bitte gebe einen Namen an. Mindestens 3 Zeichen, keine Sonderzeichen oder Zahlen.")); + return false; + } + if (!sm->isValid(email, VALIDATE_EMAIL)) { + addError(new Error("E-Mail", "Bitte gebe eine gültige E-Mail Adresse an.")); + return false; + } + if (!sm->isValid(password, VALIDATE_PASSWORD)) { + addError(new Error("Password", "Bitte gebe ein gültiges Password ein mit mindestens 8 Zeichen, Groß- und Kleinbuchstaben, mindestens einer Zahl und einem Sonderzeichen")); + return false; + } + if (passphrase.size() > 0 && !sm->isValid(passphrase, VALIDATE_PASSPHRASE)) { + addError(new Error("Merksatz", "Der Merksatz ist nicht gültig, er besteht aus 24 Wörtern, mit Komma getrennt.")); + return false; + } + mSessionUser = new User(email.data(), name.data(), password.data(), passphrase.size() ? passphrase.data() : nullptr); + return true; +} + +bool Session::loadUser(const std::string& email, const std::string& password) +{ + return true; +} \ No newline at end of file diff --git a/src/cpp/model/Session.h b/src/cpp/model/Session.h index 6aa60c2fd..0d3be48e3 100644 --- a/src/cpp/model/Session.h +++ b/src/cpp/model/Session.h @@ -10,7 +10,8 @@ #ifndef DR_LUA_WEB_MODULE_SESSION_SESSION_H #define DR_LUA_WEB_MODULE_SESSION_SESSION_H -#include "../Error/ErrorList.h" +#include "ErrorList.h" +#include "User.h" class Session : public ErrorList { @@ -18,11 +19,15 @@ public: Session(int handle); ~Session(); + bool createUser(const std::string& name, const std::string& email, const std::string& password, const std::string& passphrase); + bool loadUser(const std::string& email, const std::string& password); + inline int getHandle() { return mHandleId; } - virtual void reset() = 0; + void reset(); protected: int mHandleId; + User* mSessionUser; }; diff --git a/src/cpp/model/User.cpp b/src/cpp/model/User.cpp index e69de29bb..decbd1d74 100644 --- a/src/cpp/model/User.cpp +++ b/src/cpp/model/User.cpp @@ -0,0 +1,135 @@ +#include "User.h" +#include +#include "ed25519/ed25519.h" +#include "Poco/Util/Application.h" + +NewUser::NewUser(User* user, const char* password, const char* passphrase) + : mUser(user), mPassword(password), mPassphrase(passphrase) +{ + +} + + +NewUser::~NewUser() +{ + +} + +void NewUser::run() +{ + // create crypto key + if (!mUser->hasCryptoKey()) { + mUser->createCryptoKey(mUser->getEmail(), mPassword.data()); + } + + // generate +} + + +// ------------------------------------------------------------------------------------ + +LoginUser::LoginUser(User* user, const char* password) + : mUser(user), mPassword(password) +{ +// auto app = Poco::Util::Application::instance(); +} + +LoginUser::~LoginUser() +{ + +} + +void LoginUser::run() +{ + +} + +// ******************************************************************************* + +User::User(const char* email, const char* name, const char* password, const char* passphrase) + : mEmail(email), mFirstName(name), mCryptoKey(nullptr) +{ + +} + +User::User(const char* email, const char* password) + : mEmail(email) +{ + +} + + +User::~User() +{ + if (mCryptoKey) { + delete mCryptoKey; + } +} + + +std::string User::generateNewPassphrase(Mnemonic* word_source) +{ + unsigned int random_indices[PHRASE_WORD_COUNT]; + unsigned int str_sizes[PHRASE_WORD_COUNT]; + unsigned int phrase_buffer_size = 0; + + for (int i = 0; i < PHRASE_WORD_COUNT; i++) { + random_indices[i] = randombytes_random() % 2048; + str_sizes[i] = strlen(word_source->getWord(random_indices[i])); + 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], word_source->getWord(random_indices[i]), str_sizes[i]); + + phrase_buffer_cursor += str_sizes[i]; + phrase_buffer[phrase_buffer_cursor++] = ' '; + } + + + return phrase_buffer; +} + +void User::createCryptoKey(const char* username, const char* password) +{ + + // TODO: put it in secure location + static const unsigned char app_secret[] = { 0x21, 0xff, 0xbb, 0xc6, 0x16, 0xfe }; + + size_t username_size = strlen(username); + size_t password_size = strlen(password); + sha_context context_sha512; + //unsigned char* hash512 = (unsigned char*)malloc(SHA_512_SIZE); + if (SHA_512_SIZE < crypto_pwhash_SALTBYTES) { + addError(new Error(__FUNCTION__, "sha512 is to small for libsodium pwhash saltbytes")); + return; + } + + + + unsigned char hash512_salt[SHA_512_SIZE]; // need at least crypto_pwhash_SALTBYTES 16U + sha512_init(&context_sha512); + sha512_update(&context_sha512, (const unsigned char*)username, username_size); + sha512_update(&context_sha512, app_secret, 6); + sha512_final(&context_sha512, hash512_salt); + + unsigned char* key = (unsigned char *)malloc(crypto_box_SEEDBYTES); // 32U + + if (crypto_pwhash(key, crypto_box_SEEDBYTES, password, password_size, hash512_salt, 2U, 8388608, 2) != 0) { + addError(new ParamError(__FUNCTION__, " error creating pwd hash, maybe to much memory requestet? error:", strerror(errno))); + //printf("[User::%s] error creating pwd hash, maybe to much memory requestet? error: %s\n", __FUNCTION__, strerror(errno)); + //printf("pwd: %s\n", pwd); + return ; + } + lock(); + mCryptoKey = new ObfusArray(crypto_box_SEEDBYTES, key); + unlock(); + free(key); + + // mCryptoKey + +} \ No newline at end of file diff --git a/src/cpp/model/User.h b/src/cpp/model/User.h index e69de29bb..479ab4c8f 100644 --- a/src/cpp/model/User.h +++ b/src/cpp/model/User.h @@ -0,0 +1,72 @@ +#ifndef GRADIDO_LOGIN_SERVER_MODEL_USER_INCLUDE +#define GRADIDO_LOGIN_SERVER_MODEL_USER_INCLUDE + +#include "../Crypto/KeyPair.h" +#include +#include "ErrorList.h" +#include "Poco/Thread.h" + +class NewUser; + +class User : public ErrorList +{ + friend NewUser; +public: + // new user + User(const char* email, const char* name, const char* password, const char* passphrase); + // existing user + User(const char* email, const char* password); + + ~User(); + + static std::string generateNewPassphrase(Mnemonic* word_source); + + inline bool hasCryptoKey() { lock(); bool bRet = mCryptoKey != nullptr; unlock(); return bRet; } + inline const char* getEmail() { return mEmail.data(); } + + +protected: + void createCryptoKey(const char* email, const char* password); + + inline void lock() { mWorkingMutex->lock(); } + inline void unlock() { mWorkingMutex->unlock(); } + +private: + std::string mEmail; + std::string mFirstName; + // crypto key as obfus array + ObfusArray* mCryptoKey; + + Poco::Mutex* mWorkingMutex; + +}; + +class NewUser : public Poco::Runnable +{ +public: + NewUser(User* user, const char* password, const char* passphrase); + ~NewUser(); + + + virtual void run(); +protected: + User* mUser; + std::string mPassword; + std::string mPassphrase; + +}; + +class LoginUser : public Poco::Runnable +{ +public: + LoginUser(User* user, const char* password); + ~LoginUser(); + + virtual void run(); +protected: + User* mUser; + std::string mPassword; + +}; + +#endif //GRADIDO_LOGIN_SERVER_MODEL_USER_INCLUDE \ No newline at end of file diff --git a/src/cpsp/login.cpsp b/src/cpsp/login.cpsp index ccb238094..a769b778e 100644 --- a/src/cpsp/login.cpsp +++ b/src/cpsp/login.cpsp @@ -21,8 +21,8 @@ Login

Bitte gebe deine Zugangsdaten ein um dich einzuloggen.

- - + +

diff --git a/src/cpsp/register.cpsp b/src/cpsp/register.cpsp index 0159422ba..d31d23bf3 100644 --- a/src/cpsp/register.cpsp +++ b/src/cpsp/register.cpsp @@ -1,8 +1,20 @@ <%@ page class="RegisterPage" %> <%@ page form="true" %> <%@ page compressed="true" %> -<%! - +<%! +#include "../SingletonManager/SessionManager.h" +%> +<% + auto session = SessionManager::getInstance()->getNewSession(); + bool userReturned = false; + if(!form.empty()) { + userReturned = session->createUser( + form.get("register-name"), + form.get("register-email"), + form.get("register-password"), + form.get("register-key-existing") + ); + } %> @@ -12,17 +24,34 @@ Gradido Login Server: Register + -

Login

+

Einen neuen Account anlegen

+
+ <% if(!form.empty() && !userReturned) {%> + <%= session->getErrorsHtml() %> + <%} %>
Account anlegen

Bitte gebe deine Daten um einen Account anzulegen

- - + + "/> +

+

+ + "/>

@@ -31,13 +60,13 @@

Hast du bereits schonmal ein Gradido Konto besessen?

- +

- +

- +