fix bug which crashed server after to fast logout

This commit is contained in:
Dario 2019-10-08 11:34:14 +02:00
parent e4ffe57750
commit 9177398f48
7 changed files with 76 additions and 33 deletions

View File

@ -46,6 +46,7 @@ conan_basic_setup()
add_executable(Gradido_LoginServer ${LOCAL_SRCS}) add_executable(Gradido_LoginServer ${LOCAL_SRCS})
#SUBDIRS("src/test")
if(WIN32) if(WIN32)
@ -62,6 +63,7 @@ set(INSTALL_BINDIR "bin")
set(INSTALL_PLUGINDIR "bin") set(INSTALL_PLUGINDIR "bin")
add_subdirectory("dependencies/mariadb-connector-c") add_subdirectory("dependencies/mariadb-connector-c")
include_directories( include_directories(
"dependencies/mariadb-connector-c/include" "dependencies/mariadb-connector-c/include"
"build/dependencies/mariadb-connector-c/include" "build/dependencies/mariadb-connector-c/include"

@ -1 +1 @@
Subproject commit a0977c22d23f7e8cb596f1d9d812de74115f407b Subproject commit 7307ffb8a89d2459f0c07ea5cab27c0d3496df00

View File

@ -19,16 +19,24 @@ using namespace Poco::Data::Keywords;
int WriteEmailVerification::run() int WriteEmailVerification::run()
{ {
Profiler timeUsed; Profiler timeUsed;
Poco::UInt64 verificationCode = mSession->getEmailVerificationCode(); auto em = ErrorManager::getInstance();
//printf("[WriteEmailVerification::run] E-Mail Verification Code: %llu\n", verificationCode); //printf("[WriteEmailVerification::run] E-Mail Verification Code: %llu\n", verificationCode);
auto dbSession = ConnectionManager::getInstance()->getConnection(CONNECTION_MYSQL_LOGIN_SERVER); auto dbSession = ConnectionManager::getInstance()->getConnection(CONNECTION_MYSQL_LOGIN_SERVER);
//int user_id = mUser->getDBId(); //int user_id = mUser->getDBId();
Poco::Data::Statement insert(dbSession); Poco::Data::Statement insert(dbSession);
insert << "INSERT INTO email_opt_in (user_id, verification_code) VALUES(?,?);", insert << "INSERT INTO email_opt_in (user_id, verification_code) VALUES(?,?);",
bind(mUser->getDBId()), use(verificationCode); bind(mUser->getDBId()), use(mEmailVerificationCode);
if (1 != insert.execute()) { try {
mSession->addError(new Error("WriteEmailVerification", "error inserting email verification code")); if (1 != insert.execute()) {
return -1; em->addError(new Error("[WriteEmailVerification]", "error inserting email verification code"));
em->sendErrorsAsEmail();
return -1;
}
} catch (Poco::Exception& ex) {
em->addError(new ParamError("[WriteEmailVerification]", "error inserting email verification code", ex.displayText().data()));
em->sendErrorsAsEmail();
return -2;
} }
printf("[WriteEmailVerification] timeUsed: %s\n", timeUsed.string().data()); printf("[WriteEmailVerification] timeUsed: %s\n", timeUsed.string().data());
return 0; return 0;
@ -85,20 +93,27 @@ Session::~Session()
void Session::reset() void Session::reset()
{ {
if (mSessionUser) { lock();
delete mSessionUser;
mSessionUser = nullptr; mSessionUser = nullptr;
}
updateTimeout(); // watch out
updateState(SESSION_STATE_EMPTY); //updateTimeout();
mLastActivity = Poco::DateTime();
mState = SESSION_STATE_EMPTY;
mPassphrase = ""; mPassphrase = "";
mClientLoginIP = Poco::Net::IPAddress(); mClientLoginIP = Poco::Net::IPAddress();
mEmailVerificationCode = 0; mEmailVerificationCode = 0;
unlock();
} }
void Session::updateTimeout() void Session::updateTimeout()
{ {
lock();
mLastActivity = Poco::DateTime(); mLastActivity = Poco::DateTime();
unlock();
} }
bool Session::createUser(const std::string& name, const std::string& email, const std::string& password) bool Session::createUser(const std::string& name, const std::string& email, const std::string& password)
@ -114,7 +129,7 @@ bool Session::createUser(const std::string& name, const std::string& email, cons
return false; return false;
} }
if (!sm->isValid(password, VALIDATE_PASSWORD)) { if (!sm->isValid(password, VALIDATE_PASSWORD)) {
addError(new Error("Passwort", "Bitte gebe ein g&uuml;ltiges Password ein mit mindestens 8 Zeichen, Gro&szlig;- und Kleinbuchstaben, mindestens einer Zahl und einem Sonderzeichen ein!")); addError(new Error("Passwort", "Bitte gebe ein g&uuml;ltiges Password ein mit mindestens 8 Zeichen, Gro&szlig;- und Kleinbuchstaben, mindestens einer Zahl und einem Sonderzeichen (@$!%*?&+-) ein!"));
// @$!%*?&+- // @$!%*?&+-
if (password.size() < 8) { if (password.size() < 8) {
@ -181,7 +196,7 @@ bool Session::createUser(const std::string& name, const std::string& email, cons
createEmailVerificationCode(); createEmailVerificationCode();
UniLib::controller::TaskPtr writeEmailVerification(new WriteEmailVerification(mSessionUser, this, ServerConfig::g_CPUScheduler, 1)); UniLib::controller::TaskPtr writeEmailVerification(new WriteEmailVerification(mSessionUser, mEmailVerificationCode, ServerConfig::g_CPUScheduler, 1));
writeEmailVerification->setParentTaskPtrInArray(writeUserIntoDB, 0); writeEmailVerification->setParentTaskPtrInArray(writeUserIntoDB, 0);
writeEmailVerification->setFinishCommand(new SessionStateUpdateCommand(SESSION_STATE_EMAIL_VERIFICATION_WRITTEN, this)); writeEmailVerification->setFinishCommand(new SessionStateUpdateCommand(SESSION_STATE_EMAIL_VERIFICATION_WRITTEN, this));
writeEmailVerification->scheduleTask(writeEmailVerification); writeEmailVerification->scheduleTask(writeEmailVerification);
@ -419,6 +434,7 @@ bool Session::loadFromEmailVerificationCode(Poco::UInt64 emailVerificationCode)
void Session::updateState(SessionStates newState) void Session::updateState(SessionStates newState)
{ {
lock(); lock();
if (!mActive) return;
updateTimeout(); updateTimeout();
printf("[%s] newState: %s\n", __FUNCTION__, translateSessionStateToString(newState)); printf("[%s] newState: %s\n", __FUNCTION__, translateSessionStateToString(newState));
if (newState > mState) { if (newState > mState) {

View File

@ -62,7 +62,7 @@ public:
Poco::Net::HTTPCookie getLoginCookie(); Poco::Net::HTTPCookie getLoginCookie();
inline User* getUser() { return mSessionUser; } inline Poco::AutoPtr<User> getUser() { return mSessionUser; }
inline int getHandle() { return mHandleId; } inline int getHandle() { return mHandleId; }
@ -82,13 +82,14 @@ public:
const char* getSessionStateString(); const char* getSessionStateString();
inline SessionStates getSessionState() { SessionStates s; lock(); s = mState; unlock(); return s; } inline SessionStates getSessionState() { SessionStates s; lock(); s = mState; unlock(); return s; }
inline unsigned long long getEmailVerificationCode() { return mEmailVerificationCode; } inline Poco::UInt64 getEmailVerificationCode() { return mEmailVerificationCode; }
inline bool isActive() const { return mActive; } inline bool isActive() const { return mActive; }
inline void setActive(bool active) { mActive = active; } inline void setActive(bool active) { mActive = active; }
inline Poco::DateTime getLastActivity() { return mLastActivity; } inline Poco::DateTime getLastActivity() { return mLastActivity; }
protected: protected:
void updateTimeout(); void updateTimeout();
inline void setHandle(int newHandle) { mHandleId = newHandle; } inline void setHandle(int newHandle) { mHandleId = newHandle; }
@ -100,30 +101,31 @@ protected:
private: private:
int mHandleId; int mHandleId;
User* mSessionUser; Poco::AutoPtr<User> mSessionUser;
std::string mPassphrase; std::string mPassphrase;
Poco::DateTime mLastActivity; Poco::DateTime mLastActivity;
Poco::Net::IPAddress mClientLoginIP; Poco::Net::IPAddress mClientLoginIP;
unsigned long long mEmailVerificationCode; Poco::UInt64 mEmailVerificationCode;
SessionStates mState; SessionStates mState;
bool mActive; bool mActive;
}; };
class WriteEmailVerification : public UniLib::controller::CPUTask class WriteEmailVerification : public UniLib::controller::CPUTask
{ {
public: public:
WriteEmailVerification(User* user, Session* session, UniLib::controller::CPUSheduler* cpuScheduler, size_t taskDependenceCount = 0) WriteEmailVerification(Poco::AutoPtr<User> user, Poco::UInt64 emailVerificationCode, UniLib::controller::CPUSheduler* cpuScheduler, size_t taskDependenceCount = 0)
: UniLib::controller::CPUTask(cpuScheduler, taskDependenceCount), mUser(user), mSession(session) {} : UniLib::controller::CPUTask(cpuScheduler, taskDependenceCount), mUser(user), mEmailVerificationCode(emailVerificationCode) {}
virtual const char* getResourceType() const { return "WriteEmailVerification"; }; virtual const char* getResourceType() const { return "WriteEmailVerification"; };
virtual int run(); virtual int run();
private: private:
User* mUser; Poco::AutoPtr<User> mUser;
Session* mSession; Poco::UInt64 mEmailVerificationCode;
}; };

View File

@ -76,7 +76,7 @@ int UserWriteIntoDB::run()
// -------------------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------------------
UserWriteKeysIntoDB::UserWriteKeysIntoDB(UniLib::controller::TaskPtr parent, User* user, bool savePrivKey) UserWriteKeysIntoDB::UserWriteKeysIntoDB(UniLib::controller::TaskPtr parent, Poco::AutoPtr<User> user, bool savePrivKey)
: UniLib::controller::CPUTask(1), mUser(user), mSavePrivKey(savePrivKey) : UniLib::controller::CPUTask(1), mUser(user), mSavePrivKey(savePrivKey)
{ {
if (strcmp(parent->getResourceType(), "UserGenerateKeys") != 0) { if (strcmp(parent->getResourceType(), "UserGenerateKeys") != 0) {
@ -201,6 +201,7 @@ std::string User::generateNewPassphrase(Mnemonic* word_source)
unsigned int str_sizes[PHRASE_WORD_COUNT]; unsigned int str_sizes[PHRASE_WORD_COUNT];
unsigned int phrase_buffer_size = 0; unsigned int phrase_buffer_size = 0;
// TODO: make sure words didn't double
for (int i = 0; i < PHRASE_WORD_COUNT; i++) { for (int i = 0; i < PHRASE_WORD_COUNT; i++) {
random_indices[i] = randombytes_random() % 2048; random_indices[i] = randombytes_random() % 2048;
auto word = word_source->getWord(random_indices[i]); auto word = word_source->getWord(random_indices[i]);
@ -271,6 +272,20 @@ bool User::validatePwd(const std::string& pwd)
return false; return false;
} }
void User::duplicate()
{
mReferenceCount++;
}
void User::release()
{
mReferenceCount--;
if (0 == mReferenceCount) {
delete this;
}
}
ObfusArray* User::createCryptoKey(const std::string& password) ObfusArray* User::createCryptoKey(const std::string& password)
{ {

View File

@ -51,6 +51,10 @@ public:
bool validatePwd(const std::string& pwd); bool validatePwd(const std::string& pwd);
Poco::Data::BLOB* encrypt(const ObfusArray* data); Poco::Data::BLOB* encrypt(const ObfusArray* data);
// for poco auto ptr
void duplicate();
void release();
protected: protected:
typedef Poco::UInt64 passwordHashed; typedef Poco::UInt64 passwordHashed;
@ -66,6 +70,8 @@ protected:
inline void lock() { mWorkingMutex.lock(); } inline void lock() { mWorkingMutex.lock(); }
inline void unlock() { mWorkingMutex.unlock(); } inline void unlock() { mWorkingMutex.unlock(); }
private: private:
int mDBId; int mDBId;
std::string mEmail; std::string mEmail;
@ -78,26 +84,28 @@ private:
std::string mPublicHex; std::string mPublicHex;
Poco::Mutex mWorkingMutex; Poco::Mutex mWorkingMutex;
// for poco auto ptr
int mReferenceCount;
}; };
class UserCreateCryptoKey : public UniLib::controller::CPUTask class UserCreateCryptoKey : public UniLib::controller::CPUTask
{ {
public: public:
UserCreateCryptoKey(User* user, const std::string& password, UniLib::controller::CPUSheduler* cpuScheduler) UserCreateCryptoKey(Poco::AutoPtr<User> user, const std::string& password, UniLib::controller::CPUSheduler* cpuScheduler)
: UniLib::controller::CPUTask(cpuScheduler), mUser(user), mPassword(password) {} : UniLib::controller::CPUTask(cpuScheduler), mUser(user), mPassword(password) {}
virtual int run(); virtual int run();
virtual const char* getResourceType() const { return "UserCreateCryptoKey"; }; virtual const char* getResourceType() const { return "UserCreateCryptoKey"; };
private: private:
User* mUser; Poco::AutoPtr<User> mUser;
std::string mPassword; std::string mPassword;
}; };
class UserGenerateKeys : public UniLib::controller::CPUTask class UserGenerateKeys : public UniLib::controller::CPUTask
{ {
public: public:
UserGenerateKeys(User* user, const std::string& passphrase) UserGenerateKeys(Poco::AutoPtr<User> user, const std::string& passphrase)
: mUser(user), mPassphrase(passphrase) {} : mUser(user), mPassphrase(passphrase) {}
~UserGenerateKeys() { ~UserGenerateKeys() {
@ -108,7 +116,7 @@ public:
virtual const char* getResourceType() const { return "UserGenerateKeys"; }; virtual const char* getResourceType() const { return "UserGenerateKeys"; };
protected: protected:
User* mUser; Poco::AutoPtr<User> mUser;
std::string mPassphrase; std::string mPassphrase;
KeyPair mKeys; KeyPair mKeys;
}; };
@ -116,25 +124,25 @@ protected:
class UserWriteIntoDB : public UniLib::controller::CPUTask class UserWriteIntoDB : public UniLib::controller::CPUTask
{ {
public: public:
UserWriteIntoDB(User* user, UniLib::controller::CPUSheduler* cpuScheduler, size_t taskDependenceCount = 0) UserWriteIntoDB(Poco::AutoPtr<User> user, UniLib::controller::CPUSheduler* cpuScheduler, size_t taskDependenceCount = 0)
: UniLib::controller::CPUTask(cpuScheduler, taskDependenceCount), mUser(user) {} : UniLib::controller::CPUTask(cpuScheduler, taskDependenceCount), mUser(user) {}
virtual int run(); virtual int run();
virtual const char* getResourceType() const { return "UserWriteIntoDB"; }; virtual const char* getResourceType() const { return "UserWriteIntoDB"; };
private: private:
User* mUser; Poco::AutoPtr<User> mUser;
}; };
class UserWriteKeysIntoDB : public UniLib::controller::CPUTask class UserWriteKeysIntoDB : public UniLib::controller::CPUTask
{ {
public: public:
UserWriteKeysIntoDB(UniLib::controller::TaskPtr parent, User* user, bool savePrivKey); UserWriteKeysIntoDB(UniLib::controller::TaskPtr parent, Poco::AutoPtr<User> user, bool savePrivKey);
virtual int run(); virtual int run();
virtual const char* getResourceType() const { return "UserWriteKeysIntoDB"; }; virtual const char* getResourceType() const { return "UserWriteKeysIntoDB"; };
protected: protected:
User* mUser; Poco::AutoPtr<User> mUser;
bool mSavePrivKey; bool mSavePrivKey;
}; };

View File

@ -79,7 +79,7 @@ label:not(.grd_radio_label) {
<% if(state == PAGE_SHOW_PASSPHRASE) {%> <% if(state == PAGE_SHOW_PASSPHRASE) {%>
<div class="grd_text-max-width"> <div class="grd_text-max-width">
<div class="grd_text"> <div class="grd_text">
Schreibe dir den Merkspruch auf und packe ihn gut weg. Du brauchst ihn um deine Adresse wiederherzustellen. Wenn du ihn verlierst, sind auch deine Gradidos verloren. Schreibe dir die Passphrase auf und packe sie gut weg. Du brauchst sie um deine Adresse wiederherzustellen. Wenn du ihn verlierst, sind auch deine Gradidos verloren.
</div> </div>
<div class="grd_textarea"> <div class="grd_textarea">
<%= mSession->getPassphrase() %> <%= mSession->getPassphrase() %>