diff --git a/src/cpp/Crypto/mnemonic.h b/src/cpp/Crypto/mnemonic.h index 43ee477d4..39f12c884 100644 --- a/src/cpp/Crypto/mnemonic.h +++ b/src/cpp/Crypto/mnemonic.h @@ -12,6 +12,7 @@ */ #include "DRHashList.h" +#include #define PHRASE_WORD_COUNT 24 @@ -26,6 +27,7 @@ public: inline const char* getWord(unsigned int index) { if (index < 2048) return mWords[index]; return nullptr; } inline unsigned long getWordIndex(const char* word) { DHASH word_hash = DRMakeStringHash(word); return (long)mWordHashIndices.findByHash(word_hash); } + inline bool isWordExist(const std::string& word) { DHASH word_hash = DRMakeStringHash(word.data()); return mWordHashIndices.itemExists(word_hash); } protected: char* mWords[2048]; diff --git a/src/cpp/HTTPInterface/CheckEmailPage.cpp b/src/cpp/HTTPInterface/CheckEmailPage.cpp new file mode 100644 index 000000000..0234b76ad --- /dev/null +++ b/src/cpp/HTTPInterface/CheckEmailPage.cpp @@ -0,0 +1,233 @@ +#include "CheckEmailPage.h" +#include "Poco/Net/HTTPServerRequest.h" +#include "Poco/Net/HTTPServerResponse.h" +#include "Poco/Net/HTMLForm.h" +#include "Poco/DeflatingStream.h" + + +#line 7 "I:\\Code\\C++\\Eigene_Projekte\\Gradido_LoginServer\\src\\cpsp\\checkEmail.cpsp" + +#include "../SingletonManager/SessionManager.h" +#include "../model/User.h" +#include "Poco/Net/HTTPCookie.h" + +enum PageState +{ + PAGE_VERIFICATION_FAILED, + PAGE_ASK_PASSPHRASE, + PAGE_SHOW_PASSPHRASE, + PAGE_ASK_VERIFICATION_CODE +}; + + +CheckEmailPage::CheckEmailPage(Session* arg): + SessionHTTPRequestHandler(arg) +{ +} + + +void CheckEmailPage::handleRequest(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response) +{ + response.setChunkedTransferEncoding(true); + response.setContentType("text/html"); + bool _compressResponse(request.hasToken("Accept-Encoding", "gzip")); + if (_compressResponse) response.set("Content-Encoding", "gzip"); + + Poco::Net::HTMLForm form(request, request.stream()); +#line 20 "I:\\Code\\C++\\Eigene_Projekte\\Gradido_LoginServer\\src\\cpsp\\checkEmail.cpsp" + + auto sm = SessionManager::getInstance(); + bool hasErrors = false; + unsigned long long verificationCode = 0; + PageState state = PAGE_ASK_PASSPHRASE; + std::string uri = request.getURI(); + //printf("uri: %s\n", uri.data()); + + if(!form.empty()) { + try { + verificationCode = stoll(form.get("email-verification-code", "0")); + } catch(...) {} + } + if(!verificationCode) { + size_t pos = uri.find_last_of("/"); + try { + verificationCode = stoll(uri.substr(pos+1)); + } catch(...) {} + } + if(!verificationCode) { + state = PAGE_ASK_VERIFICATION_CODE; + } else { + // no session + if(!mSession || mSession->getEmailVerificationCode() != verificationCode) { + mSession = sm->findByEmailVerificationCode(verificationCode); + } + // no session in server, load from db + if(!mSession) { + mSession = sm->getNewSession(); + if(mSession->loadFromEmailVerificationCode(verificationCode)) { + auto cookie_id = mSession->getHandle(); + auto user_host = request.clientAddress().host(); + mSession->setClientIp(user_host); + response.addCookie(Poco::Net::HTTPCookie("user", std::to_string(cookie_id))); + } else { + sm->releseSession(mSession); + mSession = nullptr; + state = PAGE_VERIFICATION_FAILED; + } + } + if(mSession) { + mSession->updateEmailVerification(verificationCode); + hasErrors = mSession->errorCount() > 0; + + if(!hasErrors && !form.empty()) { + auto registerKeyChoice = form.get("register-key", ""); + std::string oldPassphrase = ""; + if(registerKeyChoice == "no") { + auto oldPassphrase = form.get("register-key-existing", ""); + + if(oldPassphrase != "" && User::validatePassphrase(oldPassphrase)) { + // passphrase is valid + mSession->setPassphrase(oldPassphrase); + mSession->updateState(SESSION_STATE_PASSPHRASE_SHOWN); + state = PAGE_SHOW_PASSPHRASE; + } else { + mSession->addError(new Error("Merkspruch", "Dieser Merkspruch ist ungültig, bitte überprüfen oder neu generieren (lassen).")); + } + } else if(registerKeyChoice == "yes") { + mSession->generatePassphrase(); + state = PAGE_SHOW_PASSPHRASE; + } + } + } else { + state = PAGE_VERIFICATION_FAILED; + } + } + std::ostream& _responseStream = response.send(); + Poco::DeflatingOutputStream _gzipStream(_responseStream, Poco::DeflatingStreamBuf::STREAM_GZIP, 1); + std::ostream& responseStream = _compressResponse ? _gzipStream : _responseStream; + responseStream << "\n"; + responseStream << "\n"; + responseStream << "\n"; + responseStream << "\n"; + responseStream << "\n"; + responseStream << "\n"; + responseStream << "Gradido Login Server: Email OptIn\n"; + responseStream << "\n"; + responseStream << "\n"; + responseStream << "\n"; + responseStream << "\n"; + responseStream << "\n"; + responseStream << "
\n"; + responseStream << "\t"; +#line 108 "I:\\Code\\C++\\Eigene_Projekte\\Gradido_LoginServer\\src\\cpsp\\checkEmail.cpsp" + if(mSession && hasErrors) { responseStream << "\n"; + responseStream << "\t\t"; +#line 109 "I:\\Code\\C++\\Eigene_Projekte\\Gradido_LoginServer\\src\\cpsp\\checkEmail.cpsp" + responseStream << ( mSession->getErrorsHtml() ); + responseStream << "\n"; + responseStream << "\t"; +#line 110 "I:\\Code\\C++\\Eigene_Projekte\\Gradido_LoginServer\\src\\cpsp\\checkEmail.cpsp" +} responseStream << "\n"; + responseStream << "\t

Einen neuen Account anlegen

\n"; + responseStream << "\t"; +#line 112 "I:\\Code\\C++\\Eigene_Projekte\\Gradido_LoginServer\\src\\cpsp\\checkEmail.cpsp" + if(state == PAGE_SHOW_PASSPHRASE) { responseStream << "\n"; + responseStream << "\t\t
\n"; + responseStream << "\t\t\t
\n"; + responseStream << "\t\t\t\tSchreibe 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.\n"; + responseStream << "\t\t\t
\n"; + responseStream << "\t\t\t
\n"; + responseStream << "\t\t\t\t"; +#line 118 "I:\\Code\\C++\\Eigene_Projekte\\Gradido_LoginServer\\src\\cpsp\\checkEmail.cpsp" + responseStream << ( mSession->getPassphrase() ); + responseStream << "\n"; + responseStream << "\t\t\t
\n"; + responseStream << "\t\t\tWeiter\n"; + responseStream << "\t\t
\n"; + responseStream << "\t"; +#line 122 "I:\\Code\\C++\\Eigene_Projekte\\Gradido_LoginServer\\src\\cpsp\\checkEmail.cpsp" + } else if(state == PAGE_ASK_PASSPHRASE) { responseStream << "\n"; + responseStream << "\t
\n"; + responseStream << "\t\t
\n"; + responseStream << "\t\t\tAccount anlegen\n"; + responseStream << "\t\t\t

Bitte gebe deine Daten um einen Account anzulegen

\n"; + responseStream << "\t\t\t

Hast du schonmal ein Gradido Konto besessen?

\n"; + responseStream << "\t\t\t

\n"; + responseStream << "\t\t\t\t\n"; + responseStream << "\t\t\t\t\n"; + responseStream << "\t\t\t

\n"; + responseStream << "\t\t\t

\n"; + responseStream << "\t\t\t\t\n"; + responseStream << "\t\t\t\t\n"; + responseStream << "\t\t\t

\n"; + responseStream << "\t\t\t\n"; + responseStream << "\t\t
\n"; + responseStream << "\t\t\n"; + responseStream << "\t\t\n"; + responseStream << "\t
\n"; + responseStream << "\t"; +#line 141 "I:\\Code\\C++\\Eigene_Projekte\\Gradido_LoginServer\\src\\cpsp\\checkEmail.cpsp" + } else if(state == PAGE_ASK_VERIFICATION_CODE) { responseStream << "\n"; + responseStream << "\t
\n"; + responseStream << "\t\t

Bitte gebe deinen E-Mail Verification Code ein.

\n"; + responseStream << "\t\t\n"; + responseStream << "\t\t\n"; + responseStream << "\t
\n"; + responseStream << "\t"; +#line 147 "I:\\Code\\C++\\Eigene_Projekte\\Gradido_LoginServer\\src\\cpsp\\checkEmail.cpsp" + } else if(state == PAGE_VERIFICATION_FAILED) { responseStream << "\n"; + responseStream << "\t\t"; +#line 148 "I:\\Code\\C++\\Eigene_Projekte\\Gradido_LoginServer\\src\\cpsp\\checkEmail.cpsp" + if(mSession) { responseStream << "\n"; + responseStream << "\t\t\t"; +#line 149 "I:\\Code\\C++\\Eigene_Projekte\\Gradido_LoginServer\\src\\cpsp\\checkEmail.cpsp" + if(mSession->getSessionState() == SESSION_STATE_EMAIL_VERIFICATION_SEND) { responseStream << "\n"; + responseStream << "\t\t\t\t

Bitte versuche es erneut

\n"; + responseStream << "\t\t\t\t
\n"; + responseStream << "\t\t\t\t\t\n"; + responseStream << "\t\t\t\t\t\n"; + responseStream << "\t\t\t\t
\n"; + responseStream << "\t\t\t"; +#line 155 "I:\\Code\\C++\\Eigene_Projekte\\Gradido_LoginServer\\src\\cpsp\\checkEmail.cpsp" + } else if(mSession->getSessionState() < SESSION_STATE_EMAIL_VERIFICATION_SEND) { responseStream << "\n"; + responseStream << "\t\t\t\t
Die E-Mail wurde nicht verschickt, bitte habe noch etwas Geduld.
\n"; + responseStream << "\t\t\t"; +#line 157 "I:\\Code\\C++\\Eigene_Projekte\\Gradido_LoginServer\\src\\cpsp\\checkEmail.cpsp" + } else { responseStream << "\n"; + responseStream << "\t\t\t\t
Der Account wurde schon freigeschaltet.
\n"; + responseStream << "\t\t\t\tZurück\n"; + responseStream << "\t\t\t"; +#line 160 "I:\\Code\\C++\\Eigene_Projekte\\Gradido_LoginServer\\src\\cpsp\\checkEmail.cpsp" + } responseStream << "\n"; + responseStream << "\t\t"; +#line 161 "I:\\Code\\C++\\Eigene_Projekte\\Gradido_LoginServer\\src\\cpsp\\checkEmail.cpsp" + } else { responseStream << "\n"; + responseStream << "\t\t\t

Fehler, bitte wende dich an den Server-Admin order versuche dich erneut zu registrieren.

\n"; + responseStream << "\t\t"; +#line 163 "I:\\Code\\C++\\Eigene_Projekte\\Gradido_LoginServer\\src\\cpsp\\checkEmail.cpsp" + } responseStream << "\n"; + responseStream << "\t"; +#line 164 "I:\\Code\\C++\\Eigene_Projekte\\Gradido_LoginServer\\src\\cpsp\\checkEmail.cpsp" + } else { responseStream << "\n"; + responseStream << "\t\t
\n"; + responseStream << "\t\t\tUngültige Seite, wenn du das siehst stimmt hier was nicht. Bitte wende dich an den Server-Admin. \n"; + responseStream << "\t\t
\n"; + responseStream << "\t"; +#line 168 "I:\\Code\\C++\\Eigene_Projekte\\Gradido_LoginServer\\src\\cpsp\\checkEmail.cpsp" + } responseStream << "\n"; + responseStream << "
\n"; + responseStream << "\n"; + responseStream << "\n"; + if (_compressResponse) _gzipStream.close(); +} diff --git a/src/cpp/HTTPInterface/CheckEmailPage.h b/src/cpp/HTTPInterface/CheckEmailPage.h new file mode 100644 index 000000000..69ba01e00 --- /dev/null +++ b/src/cpp/HTTPInterface/CheckEmailPage.h @@ -0,0 +1,20 @@ +#ifndef CheckEmailPage_INCLUDED +#define CheckEmailPage_INCLUDED + + +#include "Poco/Net/HTTPRequestHandler.h" + + +#include "SessionHTTPRequestHandler.h" + + +class CheckEmailPage: public SessionHTTPRequestHandler +{ +public: + CheckEmailPage(Session*); + + void handleRequest(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response); +}; + + +#endif // CheckEmailPage_INCLUDED diff --git a/src/cpp/HTTPInterface/DashboardPage.cpp b/src/cpp/HTTPInterface/DashboardPage.cpp new file mode 100644 index 000000000..5bb79c95a --- /dev/null +++ b/src/cpp/HTTPInterface/DashboardPage.cpp @@ -0,0 +1,71 @@ +#include "DashboardPage.h" +#include "Poco/Net/HTTPServerRequest.h" +#include "Poco/Net/HTTPServerResponse.h" +#include "Poco/Net/HTMLForm.h" +#include "Poco/DeflatingStream.h" + + +#line 7 "I:\\Code\\C++\\Eigene_Projekte\\Gradido_LoginServer\\src\\cpsp\\dashboard.cpsp" + +#include "../SingletonManager/SessionManager.h" + + +DashboardPage::DashboardPage(Session* arg): + SessionHTTPRequestHandler(arg) +{ +} + + +void DashboardPage::handleRequest(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response) +{ + response.setChunkedTransferEncoding(true); + response.setContentType("text/html"); + bool _compressResponse(request.hasToken("Accept-Encoding", "gzip")); + if (_compressResponse) response.set("Content-Encoding", "gzip"); + + Poco::Net::HTMLForm form(request, request.stream()); + std::ostream& _responseStream = response.send(); + Poco::DeflatingOutputStream _gzipStream(_responseStream, Poco::DeflatingStreamBuf::STREAM_GZIP, 1); + std::ostream& responseStream = _compressResponse ? _gzipStream : _responseStream; + responseStream << "\n"; +#line 10 "I:\\Code\\C++\\Eigene_Projekte\\Gradido_LoginServer\\src\\cpsp\\dashboard.cpsp" + + //Poco::Net::NameValueCollection cookies; + //request.getCookies(cookies); + if(!form.empty()) { + //form.get("email-verification-code") + } + responseStream << "\n"; + responseStream << "\n"; + responseStream << "\n"; + responseStream << "\n"; + responseStream << "\n"; + responseStream << "\n"; + responseStream << "Gradido Login Server: Dashboard\n"; + responseStream << "\n"; + responseStream << "\n"; + responseStream << "\n"; + responseStream << "\n"; + responseStream << "
\n"; + responseStream << "\t

Willkommen "; +#line 28 "I:\\Code\\C++\\Eigene_Projekte\\Gradido_LoginServer\\src\\cpsp\\dashboard.cpsp" + responseStream << ( mSession->getUser()->getName() ); + responseStream << "

\n"; + responseStream << "\t

Status

\n"; + responseStream << "\t

"; +#line 30 "I:\\Code\\C++\\Eigene_Projekte\\Gradido_LoginServer\\src\\cpsp\\dashboard.cpsp" + responseStream << ( mSession->getSessionStateString() ); + responseStream << "

\n"; + responseStream << "\t"; +#line 31 "I:\\Code\\C++\\Eigene_Projekte\\Gradido_LoginServer\\src\\cpsp\\dashboard.cpsp" + if(mSession->getSessionState() == SESSION_STATE_EMAIL_VERIFICATION_SEND) responseStream << "\n"; + responseStream << "\t

Verification Code E-Mail wurde erfolgreich an dich verschickt, bitte schaue auch in dein Spam-Verzeichnis nach wenn du sie nicht findest und klicke auf den Link den du dort findest oder kopiere den Code hier her:

\n"; + responseStream << "\t
\n"; + responseStream << "\t\t\n"; + responseStream << "\t\t\n"; + responseStream << "\t
\n"; + responseStream << "
\n"; + responseStream << "\n"; + responseStream << "\n"; + if (_compressResponse) _gzipStream.close(); +} diff --git a/src/cpp/HTTPInterface/DashboardPage.h b/src/cpp/HTTPInterface/DashboardPage.h new file mode 100644 index 000000000..2eb8fb54b --- /dev/null +++ b/src/cpp/HTTPInterface/DashboardPage.h @@ -0,0 +1,20 @@ +#ifndef DashboardPage_INCLUDED +#define DashboardPage_INCLUDED + + +#include "Poco/Net/HTTPRequestHandler.h" + + +#include "SessionHTTPRequestHandler.h" + + +class DashboardPage: public SessionHTTPRequestHandler +{ +public: + DashboardPage(Session*); + + void handleRequest(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response); +}; + + +#endif // DashboardPage_INCLUDED diff --git a/src/cpp/HTTPInterface/EmailOptInPage.cpp b/src/cpp/HTTPInterface/EmailOptInPage.cpp new file mode 100644 index 000000000..b554e9084 --- /dev/null +++ b/src/cpp/HTTPInterface/EmailOptInPage.cpp @@ -0,0 +1,138 @@ +#include "EmailOptInPage.h" +#include "Poco/Net/HTTPServerRequest.h" +#include "Poco/Net/HTTPServerResponse.h" +#include "Poco/Net/HTMLForm.h" +#include "Poco/DeflatingStream.h" + + +#line 4 "I:\\Code\\C++\\Eigene_Projekte\\Gradido_LoginServer\\src\\cpsp\\emailOptIn.cpsp" + +#include "../SingletonManager/SessionManager.h" +#include "Poco/Net/HTTPCookie.h" + + +void EmailOptInPage::handleRequest(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response) +{ + response.setChunkedTransferEncoding(true); + response.setContentType("text/html"); + bool _compressResponse(request.hasToken("Accept-Encoding", "gzip")); + if (_compressResponse) response.set("Content-Encoding", "gzip"); + + Poco::Net::HTMLForm form(request, request.stream()); +#line 8 "I:\\Code\\C++\\Eigene_Projekte\\Gradido_LoginServer\\src\\cpsp\\emailOptIn.cpsp" + + 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") + ); + if(userReturned) { + auto cookie_id = session->getHandle(); + auto user_host = request.clientAddress().toString(); + printf("cookie: %d, user_host: %s\n", cookie_id, user_host.data()); + response.addCookie(Poco::Net::HTTPCookie("user", std::to_string(cookie_id))); + } + } + std::ostream& _responseStream = response.send(); + Poco::DeflatingOutputStream _gzipStream(_responseStream, Poco::DeflatingStreamBuf::STREAM_GZIP, 1); + std::ostream& responseStream = _compressResponse ? _gzipStream : _responseStream; + responseStream << "\n"; + responseStream << "\n"; + responseStream << "\n"; + responseStream << "\n"; + responseStream << "\n"; + responseStream << "\n"; + responseStream << "Gradido Login Server: Email OptIn\n"; + responseStream << "\n"; + responseStream << "\n"; + responseStream << "\n"; + responseStream << "\n"; + responseStream << "\n"; + responseStream << "
\n"; + responseStream << "\t

Einen neuen Account anlegen

\n"; + responseStream << "\t"; +#line 46 "I:\\Code\\C++\\Eigene_Projekte\\Gradido_LoginServer\\src\\cpsp\\emailOptIn.cpsp" + if(!form.empty() && userReturned) { responseStream << "\n"; + responseStream << "\t\t
\n"; + responseStream << "\t\t\t
\n"; + responseStream << "\t\t\t\tSchreibe 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.\n"; + responseStream << "\t\t\t
\n"; + responseStream << "\t\t\t
\n"; + responseStream << "\t\t\t\t"; +#line 52 "I:\\Code\\C++\\Eigene_Projekte\\Gradido_LoginServer\\src\\cpsp\\emailOptIn.cpsp" + responseStream << ( session->getPassphrase() ); + responseStream << "\n"; + responseStream << "\t\t\t
\n"; + responseStream << "\t\t
\n"; + responseStream << "\t"; +#line 55 "I:\\Code\\C++\\Eigene_Projekte\\Gradido_LoginServer\\src\\cpsp\\emailOptIn.cpsp" + } else { responseStream << "\n"; + responseStream << "\t
\n"; + responseStream << "\t\n"; + responseStream << "\t\t"; +#line 58 "I:\\Code\\C++\\Eigene_Projekte\\Gradido_LoginServer\\src\\cpsp\\emailOptIn.cpsp" + if(!form.empty() && !userReturned) { responseStream << "\n"; + responseStream << "\t\t\t"; +#line 59 "I:\\Code\\C++\\Eigene_Projekte\\Gradido_LoginServer\\src\\cpsp\\emailOptIn.cpsp" + responseStream << ( session->getErrorsHtml() ); + responseStream << "\n"; + responseStream << "\t\t"; +#line 60 "I:\\Code\\C++\\Eigene_Projekte\\Gradido_LoginServer\\src\\cpsp\\emailOptIn.cpsp" +} responseStream << "\n"; + responseStream << "\t\t
\n"; + responseStream << "\t\t\tAccount anlegen\n"; + responseStream << "\t\t\t

Bitte gebe deine Daten um einen Account anzulegen

\n"; + responseStream << "\t\t\t

\n"; + responseStream << "\t\t\t\t\n"; + responseStream << "\t\t\t\t\n"; + responseStream << "\t\t\t

\n"; + responseStream << "\t\t\t

\n"; + responseStream << "\t\t\t\t\n"; + responseStream << "\t\t\t\t\n"; + responseStream << "\t\t\t

\n"; + responseStream << "\t\t\t

\n"; + responseStream << "\t\t\t\t\n"; + responseStream << "\t\t\t\t\n"; + responseStream << "\t\t\t

\n"; + responseStream << "\t\t\t

Hast du schonmal ein Gradido Konto besessen?

\n"; + responseStream << "\t\t\t

\n"; + responseStream << "\t\t\t\t\n"; + responseStream << "\t\t\t\t\n"; + responseStream << "\t\t\t

\n"; + responseStream << "\t\t\t

\n"; + responseStream << "\t\t\t\t\n"; + responseStream << "\t\t\t\t\n"; + responseStream << "\t\t\t

\n"; + responseStream << "\t\t\t\n"; + responseStream << "\t\t
\n"; + responseStream << "\t\t\n"; + responseStream << "\t\t\n"; + responseStream << "\t
\n"; + responseStream << "\t"; +#line 90 "I:\\Code\\C++\\Eigene_Projekte\\Gradido_LoginServer\\src\\cpsp\\emailOptIn.cpsp" + } responseStream << "\n"; + responseStream << "
\n"; + responseStream << "\n"; + responseStream << "\n"; + if (_compressResponse) _gzipStream.close(); +} diff --git a/src/cpp/HTTPInterface/EmailOptInPage.h b/src/cpp/HTTPInterface/EmailOptInPage.h new file mode 100644 index 000000000..81f2a8236 --- /dev/null +++ b/src/cpp/HTTPInterface/EmailOptInPage.h @@ -0,0 +1,15 @@ +#ifndef EmailOptInPage_INCLUDED +#define EmailOptInPage_INCLUDED + + +#include "Poco/Net/HTTPRequestHandler.h" + + +class EmailOptInPage: public Poco::Net::HTTPRequestHandler +{ +public: + void handleRequest(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response); +}; + + +#endif // EmailOptInPage_INCLUDED diff --git a/src/cpp/HTTPInterface/PageRequestHandlerFactory.cpp b/src/cpp/HTTPInterface/PageRequestHandlerFactory.cpp index 1a2f66f7d..8ce01c1f8 100644 --- a/src/cpp/HTTPInterface/PageRequestHandlerFactory.cpp +++ b/src/cpp/HTTPInterface/PageRequestHandlerFactory.cpp @@ -8,10 +8,12 @@ #include "HandleFileRequest.h" #include "DashboardPage.h" #include "CheckEmailPage.h" +#include "SaveKeysPage.h" #include "../SingletonManager/SessionManager.h" PageRequestHandlerFactory::PageRequestHandlerFactory() + : mRemoveGETParameters("^/([a-zA-Z0-9_-]*)") { } @@ -21,7 +23,10 @@ Poco::Net::HTTPRequestHandler* PageRequestHandlerFactory::createRequestHandler(c //printf("request uri: %s\n", request.getURI().data()); std::string uri = request.getURI(); + std::string url_first_part; + mRemoveGETParameters.extract(uri, url_first_part); + printf("[PageRequestHandlerFactory] uri: %s, first part: %s\n", uri.data(), url_first_part.data()); auto referer = request.find("Referer"); if (referer != request.end()) { printf("referer: %s\n", referer->second.data()); @@ -38,11 +43,15 @@ Poco::Net::HTTPRequestHandler* PageRequestHandlerFactory::createRequestHandler(c } catch (...) {} auto sm = SessionManager::getInstance(); auto s = sm->getSession(session_id); - if (uri == "/checkEmail") { + + + if (url_first_part == "/checkEmail") { return new CheckEmailPage(s); } if (s) { - + if (uri == "/saveKeys") { + return new SaveKeysPage(s); + } return new DashboardPage(s); } else { diff --git a/src/cpp/HTTPInterface/PageRequestHandlerFactory.h b/src/cpp/HTTPInterface/PageRequestHandlerFactory.h index 765f50da3..3ab68b970 100644 --- a/src/cpp/HTTPInterface/PageRequestHandlerFactory.h +++ b/src/cpp/HTTPInterface/PageRequestHandlerFactory.h @@ -2,7 +2,7 @@ #define __DR_PAGE_REQUEST_HANDLER_FACTORY_H #include "Poco/Net/HTTPRequestHandlerFactory.h" - +#include "Poco/RegularExpression.h" #define HTTP_PAGES_COUNT 1 @@ -14,6 +14,7 @@ public: Poco::Net::HTTPRequestHandler* createRequestHandler(const Poco::Net::HTTPServerRequest& request); protected: + Poco::RegularExpression mRemoveGETParameters; }; #endif // __DR_PAGE_REQUEST_HANDLER_FACTORY_H \ No newline at end of file diff --git a/src/cpp/HTTPInterface/RegisterPage.cpp b/src/cpp/HTTPInterface/RegisterPage.cpp index 7628cdce1..00903afbb 100644 --- a/src/cpp/HTTPInterface/RegisterPage.cpp +++ b/src/cpp/HTTPInterface/RegisterPage.cpp @@ -23,12 +23,17 @@ void RegisterPage::handleRequest(Poco::Net::HTTPServerRequest& request, Poco::Ne 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") - ); + if(form.get("register-password2") != form.get("register-password")) { + session->addError(new Error("Passwort", "Passwörter sind nicht identisch.")); + } else { + userReturned = session->createUser( + form.get("register-name"), + form.get("register-email"), + form.get("register-password") + ); + } if(userReturned) { auto cookie_id = session->getHandle(); //auto user_host_string = request.clientAddress().toString(); @@ -64,7 +69,7 @@ void RegisterPage::handleRequest(Poco::Net::HTTPServerRequest& request, Poco::Ne responseStream << "
\n"; responseStream << "\t

Einen neuen Account anlegen

\n"; responseStream << "\t"; -#line 48 "I:\\Code\\C++\\Eigene_Projekte\\Gradido_LoginServer\\src\\cpsp\\register.cpsp" +#line 53 "I:\\Code\\C++\\Eigene_Projekte\\Gradido_LoginServer\\src\\cpsp\\register.cpsp" if(!form.empty() && userReturned) { responseStream << "\n"; responseStream << "\t\t\n"; responseStream << "\t\t
\n"; @@ -79,19 +84,19 @@ void RegisterPage::handleRequest(Poco::Net::HTTPServerRequest& request, Poco::Ne responseStream << "\t\t\t
\n"; responseStream << "\t\t
\n"; responseStream << "\t"; -#line 61 "I:\\Code\\C++\\Eigene_Projekte\\Gradido_LoginServer\\src\\cpsp\\register.cpsp" +#line 66 "I:\\Code\\C++\\Eigene_Projekte\\Gradido_LoginServer\\src\\cpsp\\register.cpsp" } else { responseStream << "\n"; responseStream << "\t
\n"; responseStream << "\t\n"; responseStream << "\t\t"; -#line 64 "I:\\Code\\C++\\Eigene_Projekte\\Gradido_LoginServer\\src\\cpsp\\register.cpsp" +#line 69 "I:\\Code\\C++\\Eigene_Projekte\\Gradido_LoginServer\\src\\cpsp\\register.cpsp" if(!form.empty() && !userReturned) { responseStream << "\n"; responseStream << "\t\t\t"; -#line 65 "I:\\Code\\C++\\Eigene_Projekte\\Gradido_LoginServer\\src\\cpsp\\register.cpsp" +#line 70 "I:\\Code\\C++\\Eigene_Projekte\\Gradido_LoginServer\\src\\cpsp\\register.cpsp" responseStream << ( session->getErrorsHtml() ); responseStream << "\n"; responseStream << "\t\t"; -#line 66 "I:\\Code\\C++\\Eigene_Projekte\\Gradido_LoginServer\\src\\cpsp\\register.cpsp" +#line 71 "I:\\Code\\C++\\Eigene_Projekte\\Gradido_LoginServer\\src\\cpsp\\register.cpsp" } responseStream << "\n"; responseStream << "\t\t
\n"; responseStream << "\t\t\tAccount anlegen\n"; @@ -99,14 +104,14 @@ void RegisterPage::handleRequest(Poco::Net::HTTPServerRequest& request, Poco::Ne responseStream << "\t\t\t

\n"; responseStream << "\t\t\t\t\n"; responseStream << "\t\t\t\t\n"; responseStream << "\t\t\t

\n"; responseStream << "\t\t\t

\n"; responseStream << "\t\t\t\t\n"; responseStream << "\t\t\t\t\n"; responseStream << "\t\t\t

\n"; @@ -114,12 +119,16 @@ void RegisterPage::handleRequest(Poco::Net::HTTPServerRequest& request, Poco::Ne responseStream << "\t\t\t\t\n"; responseStream << "\t\t\t\t\n"; responseStream << "\t\t\t

\n"; + responseStream << "\t\t\t

\n"; + responseStream << "\t\t\t\t\n"; + responseStream << "\t\t\t\t\n"; + responseStream << "\t\t\t

\n"; responseStream << "\t\t
\n"; responseStream << "\t\t\n"; responseStream << "\t\t\n"; responseStream << "\t
\n"; responseStream << "\t"; -#line 86 "I:\\Code\\C++\\Eigene_Projekte\\Gradido_LoginServer\\src\\cpsp\\register.cpsp" +#line 95 "I:\\Code\\C++\\Eigene_Projekte\\Gradido_LoginServer\\src\\cpsp\\register.cpsp" } responseStream << "\n"; responseStream << "\n"; responseStream << "\n"; diff --git a/src/cpp/HTTPInterface/SaveKeysPage.cpp b/src/cpp/HTTPInterface/SaveKeysPage.cpp new file mode 100644 index 000000000..21a74ab9c --- /dev/null +++ b/src/cpp/HTTPInterface/SaveKeysPage.cpp @@ -0,0 +1,121 @@ +#include "SaveKeysPage.h" +#include "Poco/Net/HTTPServerRequest.h" +#include "Poco/Net/HTTPServerResponse.h" +#include "Poco/Net/HTMLForm.h" +#include "Poco/DeflatingStream.h" + + +#line 7 "I:\\Code\\C++\\Eigene_Projekte\\Gradido_LoginServer\\src\\cpsp\\saveKeys.cpsp" + + +#include "../model/Session.h" + + + +SaveKeysPage::SaveKeysPage(Session* arg): + SessionHTTPRequestHandler(arg) +{ +} + + +void SaveKeysPage::handleRequest(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response) +{ + response.setChunkedTransferEncoding(true); + response.setContentType("text/html"); + bool _compressResponse(request.hasToken("Accept-Encoding", "gzip")); + if (_compressResponse) response.set("Content-Encoding", "gzip"); + + Poco::Net::HTMLForm form(request, request.stream()); +#line 12 "I:\\Code\\C++\\Eigene_Projekte\\Gradido_LoginServer\\src\\cpsp\\saveKeys.cpsp" + + + bool hasErrors = mSession->errorCount() > 0; + bool hasPassword = mSession->getUser()->hasCryptoKey(); + + if(!form.empty()) { + } + std::ostream& _responseStream = response.send(); + Poco::DeflatingOutputStream _gzipStream(_responseStream, Poco::DeflatingStreamBuf::STREAM_GZIP, 1); + std::ostream& responseStream = _compressResponse ? _gzipStream : _responseStream; + responseStream << "\n"; + responseStream << "\n"; + responseStream << "\n"; + responseStream << "\n"; + responseStream << "\n"; + responseStream << "\n"; + responseStream << "Gradido Login Server: Daten auf Server speichern?\n"; + responseStream << "\n"; + responseStream << "\n"; + responseStream << "\n"; + responseStream << "\n"; + responseStream << "\n"; + responseStream << "
\n"; + responseStream << "\t"; +#line 40 "I:\\Code\\C++\\Eigene_Projekte\\Gradido_LoginServer\\src\\cpsp\\saveKeys.cpsp" + if(hasErrors) { responseStream << "\n"; + responseStream << "\t\t"; +#line 41 "I:\\Code\\C++\\Eigene_Projekte\\Gradido_LoginServer\\src\\cpsp\\saveKeys.cpsp" + responseStream << ( mSession->getErrorsHtml() ); + responseStream << "\n"; + responseStream << "\t"; +#line 42 "I:\\Code\\C++\\Eigene_Projekte\\Gradido_LoginServer\\src\\cpsp\\saveKeys.cpsp" +} responseStream << "\n"; + responseStream << "\t

Daten speichern

\n"; + responseStream << "\t
\n"; + responseStream << "\t\t
\n"; + responseStream << "\t\t\tGradido Private Key speichern\n"; + responseStream << "\t\t\t
\n"; + responseStream << "\t\t\t\t

Möchtest du deinen Gradido Private Key auf dem Server mit deinem Passwort verschlüsselt speichern?

\n"; + responseStream << "\t\t\t\t

Wenn du ihn speicherst brauchst du dich in Zukunft nur mit deiner E-Mail und deinem Passwort einzuloggen.

\n"; + responseStream << "\t\t\t\t

Wenn du ihn nicht speicherst, müsstest du jedes mal wenn du eine Transaktion machen willst, deine Passphrase hier reinkopieren.

\n"; + responseStream << "\t\t\t
\n"; + responseStream << "\t\t\t

\n"; + responseStream << "\t\t\t\t\n"; + responseStream << "\t\t\t\t\n"; + responseStream << "\t\t\t

\n"; + responseStream << "\t\t\t"; +#line 56 "I:\\Code\\C++\\Eigene_Projekte\\Gradido_LoginServer\\src\\cpsp\\saveKeys.cpsp" + if(!hasPassword) { responseStream << "\n"; + responseStream << "\t\t\t\t

Ich brauche nochmal dein Passwort wenn du dich für ja entscheidest.

\n"; + responseStream << "\t\t\t\t

\n"; + responseStream << "\t\t\t\t\t\n"; + responseStream << "\t\t\t\t\t\n"; + responseStream << "\t\t\t\t

\n"; + responseStream << "\t\t\t"; +#line 62 "I:\\Code\\C++\\Eigene_Projekte\\Gradido_LoginServer\\src\\cpsp\\saveKeys.cpsp" + } responseStream << "\n"; + responseStream << "\t\t\t

\n"; + responseStream << "\t\t\t\t\n"; + responseStream << "\t\t\t\t\n"; + responseStream << "\t\t\t

\n"; + responseStream << "\t\t
\n"; + responseStream << "\t\t
\n"; + responseStream << "\t\t\tPassphrase speichern\n"; + responseStream << "\t\t\t
\n"; + responseStream << "\t\t\t\t

Möchtest du deine Passphrase mit dem Server-Admin-Key verschlüsselt auf dem Server gespeichert haben?

\n"; + responseStream << "\t\t\t\t

Dann kann dir der Server-Admin deine Passphrase zuschicken wenn du sie verlegt hast.

\n"; + responseStream << "\t\t\t
\n"; + responseStream << "\t\t\t

\n"; + responseStream << "\t\t\t\t\n"; + responseStream << "\t\t\t\t\n"; + responseStream << "\t\t\t

\n"; + responseStream << "\t\t\t

\n"; + responseStream << "\t\t\t\t\n"; + responseStream << "\t\t\t\t\n"; + responseStream << "\t\t\t

\n"; + responseStream << "\t\t
\n"; + responseStream << "\t\t\n"; + responseStream << "\t
\n"; + responseStream << "
\n"; + responseStream << "\n"; + responseStream << "\n"; + if (_compressResponse) _gzipStream.close(); +} diff --git a/src/cpp/HTTPInterface/SaveKeysPage.h b/src/cpp/HTTPInterface/SaveKeysPage.h new file mode 100644 index 000000000..84d9e8d21 --- /dev/null +++ b/src/cpp/HTTPInterface/SaveKeysPage.h @@ -0,0 +1,20 @@ +#ifndef SaveKeysPage_INCLUDED +#define SaveKeysPage_INCLUDED + + +#include "Poco/Net/HTTPRequestHandler.h" + + +#include "SessionHTTPRequestHandler.h" + + +class SaveKeysPage: public SessionHTTPRequestHandler +{ +public: + SaveKeysPage(Session*); + + void handleRequest(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response); +}; + + +#endif // SaveKeysPage_INCLUDED diff --git a/src/cpp/HTTPInterface/SessionHTTPRequestHandler.h b/src/cpp/HTTPInterface/SessionHTTPRequestHandler.h new file mode 100644 index 000000000..75bd37fd1 --- /dev/null +++ b/src/cpp/HTTPInterface/SessionHTTPRequestHandler.h @@ -0,0 +1,18 @@ +#ifndef SESSION_HTTP_REQUEST_HANDLER_INCLUDED +#define SESSION_HTTP_REQUEST_HANDLER_INCLUDED + +#include "../model/Session.h" +#include "Poco/Net/HTTPRequestHandler.h" + + +class SessionHTTPRequestHandler : public Poco::Net::HTTPRequestHandler +{ +public: + SessionHTTPRequestHandler(Session* session) : mSession(session) {} + +protected: + Session* mSession; +}; + + +#endif // SESSION_HTTP_REQUEST_HANDLER_INCLUDED diff --git a/src/cpp/SingletonManager/ConnectionManager.h b/src/cpp/SingletonManager/ConnectionManager.h index e62ce8e46..03571f750 100644 --- a/src/cpp/SingletonManager/ConnectionManager.h +++ b/src/cpp/SingletonManager/ConnectionManager.h @@ -40,7 +40,7 @@ public: { case CONNECTION_MYSQL_LOGIN_SERVER: case CONNECTION_MYSQL_PHP_SERVER: - return mSessionPools.get(mSessionPoolNames[type]); + return mSessionPools.getPool(mSessionPoolNames[type]).get(); default: addError(new ParamError("[ConnectionManager::getConnection]", "Connection Type unknown", std::to_string(type))); break; diff --git a/src/cpp/SingletonManager/ErrorManager.cpp b/src/cpp/SingletonManager/ErrorManager.cpp index f841d32b5..1481107c1 100644 --- a/src/cpp/SingletonManager/ErrorManager.cpp +++ b/src/cpp/SingletonManager/ErrorManager.cpp @@ -68,6 +68,7 @@ void ErrorManager::addError(Error* error) if (it == mErrorsMap.end()) { list = new std::list; + mErrorsMap.insert(std::pair*>(id, list)); } else { list = it->second; @@ -78,6 +79,7 @@ void ErrorManager::addError(Error* error) } } list->push_back(error); + mWorkingMutex.unlock(); } @@ -97,7 +99,8 @@ void ErrorManager::sendErrorsAsEmail() content += "\n"; for (auto it2 = error_list_functions->begin(); it2 != error_list_functions->end(); it2++) { content += "\t"; - content += (*it2)->getMessage(); + size_t functionNameSize = strlen((*it2)->getFunctionName()); + content += (*it2)->getString().substr(functionNameSize+1); delete (*it2); content += "\n"; } diff --git a/src/cpp/model/Session.cpp b/src/cpp/model/Session.cpp index 19d6a41e0..2f90c4159 100644 --- a/src/cpp/model/Session.cpp +++ b/src/cpp/model/Session.cpp @@ -1,4 +1,5 @@ #include "Session.h" +#include "Profiler.h" #include "../ServerConfig.h" #include "Poco/RegularExpression.h" @@ -18,12 +19,12 @@ using namespace Poco::Data::Keywords; int WriteEmailVerification::run() { auto verificationCode = mSession->getEmailVerificationCode(); - + printf("{[WriteEmailVerification::run] E-Mail Verification Code: %llu\n", verificationCode); auto dbSession = ConnectionManager::getInstance()->getConnection(CONNECTION_MYSQL_LOGIN_SERVER); int user_id = mUser->getDBId(); Poco::Data::Statement insert(dbSession); insert << "INSERT INTO email_opt_in (user_id, verification_code) VALUES(?,?);", - use(user_id), use(verificationCode); + use(user_id), bind(verificationCode); if (1 != insert.execute()) { mSession->addError(new Error("WriteEmailVerification", "error inserting email verification code")); return -1; @@ -47,7 +48,7 @@ Session::Session(int handle) Session::~Session() { - + reset(); } @@ -68,6 +69,7 @@ void Session::updateTimeout() bool Session::createUser(const std::string& name, const std::string& email, const std::string& password) { + Profiler usedTime; 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.")); @@ -159,14 +161,15 @@ bool Session::createUser(const std::string& name, const std::string& email, cons // generate and write email verification into db // send email - + printf("[Session::createUser] time: %s\n", usedTime.string().data()); return true; } bool Session::updateEmailVerification(unsigned long long emailVerificationCode) { - const char* funcName = "Session::updateEmailVerification"; + Profiler usedTime; + const static char* funcName = "Session::updateEmailVerification"; auto em = ErrorManager::getInstance(); if(mEmailVerificationCode == emailVerificationCode) { if (mSessionUser && mSessionUser->getDBId() == 0) { @@ -189,6 +192,7 @@ bool Session::updateEmailVerification(unsigned long long emailVerificationCode) em->sendErrorsAsEmail(); } updateState(SESSION_STATE_EMAIL_VERIFICATION_CODE_CHECKED); + printf("[%s] time: %s\n", funcName, usedTime.string().data()); return true; } else { @@ -196,15 +200,18 @@ bool Session::updateEmailVerification(unsigned long long emailVerificationCode) em->sendErrorsAsEmail(); } if (!updated_rows) { - addError(new Error("E-Mail Verification", "Der Code stimmt nicht, bitte überprüfe ihn nochmal oder registriere dich erneut oder wende dich an den Server-Admin")); + addError(new Error("E-Mail Verification", "Der Code stimmt nicht, bitte überprüfe ihn nochmal oder registriere dich erneut oder wende dich an den Server-Admin")); + printf("[%s] time: %s\n", funcName, usedTime.string().data()); return false; } } else { - addError(new Error("E-Mail Verification", "Falscher Code für aktiven Login")); + addError(new Error("E-Mail Verification", "Falscher Code für aktiven Login")); + printf("[%s] time: %s\n", funcName, usedTime.string().data()); return false; } + printf("[%s] time: %s\n", funcName, usedTime.string().data()); return false; } @@ -215,6 +222,58 @@ bool Session::loadUser(const std::string& email, const std::string& password) return true; } +bool Session::loadFromEmailVerificationCode(unsigned long long emailVerificationCode) +{ + Profiler usedTime; + const static char* funcName = "Session::loadFromEmailVerificationCode"; + auto em = ErrorManager::getInstance(); + auto dbConnection = ConnectionManager::getInstance()->getConnection(CONNECTION_MYSQL_LOGIN_SERVER); + + /*Poco::Data::Statement select(dbConnection); + int user_id = 0; + select << "SELECT user_id FROM email_opt_in WHERE verification_code=?", into(user_id), use(emailVerificationCode); + try { + if (select.execute() == 0) { + addError(new Error("E-Mail Verification", "Der Code konnte nicht in der Datenbank gefunden werden.")); + return false; + } + } + catch (Poco::Exception& ex) { + em->addError(new ParamError(funcName, "error selecting verification code entry", ex.displayText().data())); + em->sendErrorsAsEmail(); + return false; + }*/ + Poco::Data::Statement select(dbConnection); + std::string email, name; + select.reset(dbConnection); + select << "SELECT email, name FROM users where id = (SELECT user_id FROM email_opt_in WHERE verification_code=?)", + into(email), into(name), use(emailVerificationCode); + try { + size_t rowCount = select.execute(); + if (rowCount != 1) { + em->addError(new ParamError(funcName, "select user by email verification code work not like expected, selected row count", rowCount)); + em->sendErrorsAsEmail(); + } + if (rowCount < 0) { + addError(new Error("E-Mail Verification", "Konnte keinen passenden Account finden.")); + return false; + } + + mSessionUser = new User(email.data(), name.data()); + mSessionUser->loadEntryDBId(ConnectionManager::getInstance()->getConnection(CONNECTION_MYSQL_LOGIN_SERVER)); + mEmailVerificationCode = emailVerificationCode; + updateState(SESSION_STATE_EMAIL_VERIFICATION_CODE_CHECKED); + printf("[Session::loadFromEmailVerificationCode] time: %s\n", usedTime.string().data()); + return true; + } + catch (const Poco::Exception& ex) { + em->addError(new ParamError(funcName, "error selecting user from verification code", ex.displayText().data())); + em->sendErrorsAsEmail(); + } + + return false; +} + void Session::updateState(SessionStates newState) { lock(); @@ -243,6 +302,9 @@ const char* Session::translateSessionStateToString(SessionStates state) case SESSION_STATE_USER_WRITTEN: return "User saved"; case SESSION_STATE_EMAIL_VERIFICATION_WRITTEN: return "E-Mail verification code saved"; case SESSION_STATE_EMAIL_VERIFICATION_SEND: return "Verification E-Mail sended"; + case SESSION_STATE_EMAIL_VERIFICATION_CODE_CHECKED: return "Verification Code checked"; + case SESSION_STATE_PASSPHRASE_GENERATED: return "Passphrase generated"; + case SESSION_STATE_PASSPHRASE_SHOWN: return "Passphrase shown"; case SESSION_STATE_KEY_PAIR_GENERATED: return "Gradido Address created"; case SESSION_STATE_KEY_PAIR_WRITTEN: return "Gradido Address saved"; default: return "unknown"; @@ -258,4 +320,26 @@ void Session::createEmailVerificationCode() code_p[i] = randombytes_random(); } +} +/* +bool Session::useOrGeneratePassphrase(const std::string& passphase) +{ + if (passphase != "" && User::validatePassphrase(passphase)) { + // passphrase is valid + setPassphrase(passphase); + updateState(SESSION_STATE_PASSPHRASE_SHOWN); + return true; + } + else { + mPassphrase = User::generateNewPassphrase(&ServerConfig::g_Mnemonic_WordLists[ServerConfig::MNEMONIC_BIP0039_SORTED_ORDER]); + updateState(SESSION_STATE_PASSPHRASE_GENERATED); + return true; + } +} +*/ +bool Session::generatePassphrase() +{ + mPassphrase = User::generateNewPassphrase(&ServerConfig::g_Mnemonic_WordLists[ServerConfig::MNEMONIC_BIP0039_SORTED_ORDER]); + updateState(SESSION_STATE_PASSPHRASE_GENERATED); + return true; } \ No newline at end of file diff --git a/src/cpp/model/Session.h b/src/cpp/model/Session.h index 9c136fafd..65c293d77 100644 --- a/src/cpp/model/Session.h +++ b/src/cpp/model/Session.h @@ -29,6 +29,8 @@ enum SessionStates { SESSION_STATE_EMAIL_VERIFICATION_WRITTEN, SESSION_STATE_EMAIL_VERIFICATION_SEND, SESSION_STATE_EMAIL_VERIFICATION_CODE_CHECKED, + SESSION_STATE_PASSPHRASE_GENERATED, + SESSION_STATE_PASSPHRASE_SHOWN, SESSION_STATE_KEY_PAIR_GENERATED, SESSION_STATE_KEY_PAIR_WRITTEN, SESSION_STATE_COUNT @@ -49,12 +51,16 @@ public: // TODO: check if email exist and if not, fake waiting on password hashing with profiled times of real password hashing bool loadUser(const std::string& email, const std::string& password); + bool loadFromEmailVerificationCode(unsigned long long emailVerificationCode); + bool updateEmailVerification(unsigned long long emailVerificationCode); inline User* getUser() { return mSessionUser; } inline int getHandle() { return mHandleId; } - inline const char* getPassphrase() { return mPassphrase.data(); } + inline void setPassphrase(const std::string& passphrase) { mPassphrase = passphrase; } + inline const std::string& getPassphrase() { return mPassphrase; } + bool generatePassphrase(); inline void setClientIp(Poco::Net::IPAddress ip) { mClientLoginIP = ip; } diff --git a/src/cpp/model/User.cpp b/src/cpp/model/User.cpp index f1d88d68d..6852711c8 100644 --- a/src/cpp/model/User.cpp +++ b/src/cpp/model/User.cpp @@ -1,4 +1,5 @@ #include "User.h" +#include "Profiler.h" #include #include "ed25519/ed25519.h" #include "Poco/Util/Application.h" @@ -81,10 +82,10 @@ int UserWriteIntoDB::run() User::User(const char* email, const char* name) - : mDBId(0), mEmail(email), mFirstName(name), mCryptoKey(nullptr) + : mDBId(0), mEmail(email), mFirstName(name), mPasswordHashed(0), mCryptoKey(nullptr) { //crypto_shorthash(mPasswordHashed, (const unsigned char*)password, strlen(password), *ServerConfig::g_ServerCryptoKey); - memset(mPasswordHashed, 0, crypto_shorthash_BYTES); + //memset(mPasswordHashed, 0, crypto_shorthash_BYTES); } @@ -123,9 +124,29 @@ std::string User::generateNewPassphrase(Mnemonic* word_source) return phrase_buffer; } +bool User::validatePassphrase(const std::string& passphrase) +{ + std::istringstream iss(passphrase); + std::vector results(std::istream_iterator{iss}, + std::istream_iterator()); + for (int i = 0; i < ServerConfig::Mnemonic_Types::MNEMONIC_MAX; i++) { + auto m = ServerConfig::g_Mnemonic_WordLists[i]; + bool existAll = true; + for (auto it = results.begin(); it != results.end(); it++) { + if (!m.isWordExist(*it)) { + existAll = false; + continue; + } + } + if (existAll) return true; + } + return false; +} + void User::createCryptoKey(const std::string& password) { + Profiler timeUsed; // TODO: put it in secure location static const unsigned char app_secret[] = { 0x21, 0xff, 0xbb, 0xc6, 0x16, 0xfe }; @@ -151,14 +172,17 @@ void User::createCryptoKey(const std::string& password) //printf("pwd: %s\n", pwd); return ; } - crypto_shorthash(mPasswordHashed, key, crypto_box_SEEDBYTES, *ServerConfig::g_ServerCryptoKey); + if (sizeof(mPasswordHashed) != crypto_shorthash_BYTES) { + throw Poco::Exception("crypto_shorthash_BYTES != sizeof(mPasswordHashed)"); + } + crypto_shorthash((unsigned char*)&mPasswordHashed, key, crypto_box_SEEDBYTES, *ServerConfig::g_ServerCryptoKey); lock(); mCryptoKey = new ObfusArray(crypto_box_SEEDBYTES, key); unlock(); free(key); // mCryptoKey - + printf("[User::createCryptoKey] time used: %s\n", timeUsed.string().data()); } Poco::Data::Statement User::insertIntoDB(Poco::Data::Session session) @@ -166,10 +190,11 @@ Poco::Data::Statement User::insertIntoDB(Poco::Data::Session session) Poco::Data::Statement insert(session); - Poco::Data::BLOB pwd(mPasswordHashed, crypto_shorthash_BYTES); + //Poco::Data::BLOB pwd(&mPasswordHashed[0], crypto_shorthash_BYTES); + printf("[User::insertIntoDB] password hashed: %llu\n", mPasswordHashed); insert << "INSERT INTO users (email, name, password) VALUES(?, ?, ?);", - use(mEmail), use(mFirstName), bind(pwd); + use(mEmail), use(mFirstName), bind(mPasswordHashed); return insert; } diff --git a/src/cpp/model/User.h b/src/cpp/model/User.h index d88fb7b08..4f2e533b6 100644 --- a/src/cpp/model/User.h +++ b/src/cpp/model/User.h @@ -26,6 +26,9 @@ public: ~User(); static std::string generateNewPassphrase(Mnemonic* word_source); + static bool validatePassphrase(const std::string& passphrase); + + bool loadEntryDBId(Poco::Data::Session session); inline bool hasCryptoKey() { lock(); bool bRet = mCryptoKey != nullptr; unlock(); return bRet; } inline const char* getEmail() const { return mEmail.data(); } @@ -36,7 +39,7 @@ public: protected: void createCryptoKey(const std::string& password); Poco::Data::Statement insertIntoDB(Poco::Data::Session session); - bool loadEntryDBId(Poco::Data::Session session); + inline void lock() { mWorkingMutex.lock(); } inline void unlock() { mWorkingMutex.unlock(); } @@ -45,7 +48,7 @@ private: int mDBId; std::string mEmail; std::string mFirstName; - unsigned char mPasswordHashed[crypto_shorthash_BYTES]; + unsigned long long mPasswordHashed; // crypto key as obfus array ObfusArray* mCryptoKey; diff --git a/src/cpp/tasks/Task.cpp b/src/cpp/tasks/Task.cpp index f45eee78e..ae5e74b76 100644 --- a/src/cpp/tasks/Task.cpp +++ b/src/cpp/tasks/Task.cpp @@ -11,7 +11,7 @@ namespace UniLib { Task::Task(size_t taskPointerArraySize) : mTaskScheduled(false), mFinishCommand(nullptr), mParentTaskPtrArray(new TaskPtr[taskPointerArraySize]), mParentTaskPtrArraySize(taskPointerArraySize), - mDeleted(false) + mDeleted(false), mFinished(false), mReferenceCount(1) { } diff --git a/src/cpsp/checkEmail.cpsp b/src/cpsp/checkEmail.cpsp index 5a85e13ec..4e653bc9f 100644 --- a/src/cpsp/checkEmail.cpsp +++ b/src/cpsp/checkEmail.cpsp @@ -1,27 +1,89 @@ <%@ page class="CheckEmailPage" %> +<%@ page baseClass="SessionHTTPRequestHandler" %> +<%@ page ctorArg="Session*" %> +<%@ header include="SessionHTTPRequestHandler.h" %> <%@ page form="true" %> <%@ page compressed="true" %> <%! #include "../SingletonManager/SessionManager.h" +#include "../model/User.h" #include "Poco/Net/HTTPCookie.h" enum PageState { PAGE_VERIFICATION_FAILED, PAGE_ASK_PASSPHRASE, - PAGE_SHOW_PASSPHRASE + PAGE_SHOW_PASSPHRASE, + PAGE_ASK_VERIFICATION_CODE }; %> <%% auto sm = SessionManager::getInstance(); bool hasErrors = false; + unsigned long long verificationCode = 0; PageState state = PAGE_ASK_PASSPHRASE; std::string uri = request.getURI(); - printf("uri: %s\n", uri.data()); - if(!mSession) {// || mSession->getEmailVerificationCode() != ) { - //mSession = sm->findByEmailVerificationCode(); - } + //printf("uri: %s\n", uri.data()); + if(!form.empty()) { + try { + verificationCode = stoll(form.get("email-verification-code", "0")); + } catch(...) {} + } + if(!verificationCode) { + size_t pos = uri.find_last_of("/"); + try { + verificationCode = stoll(uri.substr(pos+1)); + } catch(...) {} + } + if(!verificationCode) { + state = PAGE_ASK_VERIFICATION_CODE; + } else { + // no session + if(!mSession || mSession->getEmailVerificationCode() != verificationCode) { + mSession = sm->findByEmailVerificationCode(verificationCode); + } + // no session in server, load from db + if(!mSession) { + mSession = sm->getNewSession(); + if(mSession->loadFromEmailVerificationCode(verificationCode)) { + auto cookie_id = mSession->getHandle(); + auto user_host = request.clientAddress().host(); + mSession->setClientIp(user_host); + response.addCookie(Poco::Net::HTTPCookie("user", std::to_string(cookie_id))); + } else { + sm->releseSession(mSession); + mSession = nullptr; + state = PAGE_VERIFICATION_FAILED; + } + } + if(mSession) { + mSession->updateEmailVerification(verificationCode); + hasErrors = mSession->errorCount() > 0; + + if(!hasErrors && !form.empty()) { + auto registerKeyChoice = form.get("passphrase", ""); + std::string oldPassphrase = ""; + if(registerKeyChoice == "no") { + auto oldPassphrase = form.get("passphrase-existing", ""); + + if(oldPassphrase != "" && User::validatePassphrase(oldPassphrase)) { + // passphrase is valid + mSession->setPassphrase(oldPassphrase); + mSession->updateState(SESSION_STATE_PASSPHRASE_SHOWN); + state = PAGE_SHOW_PASSPHRASE; + } else { + mSession->addError(new Error("Merkspruch", "Dieser Merkspruch ist ungültig, bitte überprüfen oder neu generieren (lassen).")); + } + } else if(registerKeyChoice == "yes") { + mSession->generatePassphrase(); + state = PAGE_SHOW_PASSPHRASE; + } + } + } else { + state = PAGE_VERIFICATION_FAILED; + } + } %> @@ -43,7 +105,7 @@ label:not(.grd_radio_label) {
- <% if(hasErrors) {%> + <% if(mSession && hasErrors) {%> <%= mSession->getErrorsHtml() %> <%} %>

Einen neuen Account anlegen

@@ -55,6 +117,7 @@ label:not(.grd_radio_label) {
<%= mSession->getPassphrase() %>
+ Weiter
<% } else if(state == PAGE_ASK_PASSPHRASE) { %>
@@ -63,30 +126,40 @@ label:not(.grd_radio_label) {

Bitte gebe deine Daten um einen Account anzulegen

Hast du schonmal ein Gradido Konto besessen?

- - + +

- - + +

- + - +
+ <% } else if(state == PAGE_ASK_VERIFICATION_CODE) { %> +
+

Bitte gebe deinen E-Mail Verification Code ein.

+ + +
<% } else if(state == PAGE_VERIFICATION_FAILED) { %> - <% if(mSession->getSessionState() == SESSION_STATE_EMAIL_VERIFICATION_SEND) { %> -

Bitte versuche es erneut

-
- - -
- <% } else if(mSession->getSessionState() < SESSION_STATE_EMAIL_VERIFICATION_SEND) { %> -
Die E-Mail wurde nicht verschickt, bitte habe noch etwas Geduld.
+ <% if(mSession) { %> + <% if(mSession->getSessionState() == SESSION_STATE_EMAIL_VERIFICATION_SEND) { %> +

Bitte versuche es erneut

+
+ + +
+ <% } else if(mSession->getSessionState() < SESSION_STATE_EMAIL_VERIFICATION_SEND) { %> +
Die E-Mail wurde nicht verschickt, bitte habe noch etwas Geduld.
+ <% } else { %> +
Der Account wurde schon freigeschaltet.
+ Zurück + <% } %> <% } else { %> -
Der Account wurde schon freigeschaltet.
- Zurück +

Fehler, bitte wende dich an den Server-Admin order versuche dich erneut zu registrieren.

<% } %> <% } else { %>
diff --git a/src/cpsp/dashboard.cpsp b/src/cpsp/dashboard.cpsp index 140a75169..4fcb68c98 100644 --- a/src/cpsp/dashboard.cpsp +++ b/src/cpsp/dashboard.cpsp @@ -1,4 +1,7 @@ <%@ page class="DashboardPage" %> +<%@ page baseClass="SessionHTTPRequestHandler" %> +<%@ page ctorArg="Session*" %> +<%@ header include="SessionHTTPRequestHandler.h" %> <%@ page form="true" %> <%@ page compressed="true" %> <%! diff --git a/src/cpsp/register.cpsp b/src/cpsp/register.cpsp index da78ce842..c01c3009b 100644 --- a/src/cpsp/register.cpsp +++ b/src/cpsp/register.cpsp @@ -8,12 +8,17 @@ <%% 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") - ); + if(form.get("register-password2") != form.get("register-password")) { + session->addError(new Error("Passwort", "Passwörter sind nicht identisch.")); + } else { + userReturned = session->createUser( + form.get("register-name"), + form.get("register-email"), + form.get("register-password") + ); + } if(userReturned) { auto cookie_id = session->getHandle(); //auto user_host_string = request.clientAddress().toString(); @@ -79,6 +84,10 @@ label:not(.grd_radio_label) {

+

+ + +

diff --git a/src/cpsp/saveKeys.cpsp b/src/cpsp/saveKeys.cpsp new file mode 100644 index 000000000..1d2d8fdd7 --- /dev/null +++ b/src/cpsp/saveKeys.cpsp @@ -0,0 +1,87 @@ +<%@ page class="SaveKeysPage" %> +<%@ page baseClass="SessionHTTPRequestHandler" %> +<%@ page ctorArg="Session*" %> +<%@ header include="SessionHTTPRequestHandler.h" %> +<%@ page form="true" %> +<%@ page compressed="true" %> +<%! + +#include "../model/Session.h" + +%> +<%% + + bool hasErrors = mSession->errorCount() > 0; + bool hasPassword = mSession->getUser()->hasCryptoKey(); + + if(!form.empty()) { + } +%> + + + + + +Gradido Login Server: Daten auf Server speichern? + + + + + +
+ <% if(hasErrors) {%> + <%= mSession->getErrorsHtml() %> + <%} %> +

Daten speichern

+
+
+ Gradido Private Key speichern +
+

Möchtest du deinen Gradido Private Key auf dem Server mit deinem Passwort verschlüsselt speichern?

+

Wenn du ihn speicherst brauchst du dich in Zukunft nur mit deiner E-Mail und deinem Passwort einzuloggen.

+

Wenn du ihn nicht speicherst, müsstest du jedes mal wenn du eine Transaktion machen willst, deine Passphrase hier reinkopieren.

+
+

+ + +

+ <% if(!hasPassword) { %> +

Ich brauche nochmal dein Passwort wenn du dich für ja entscheidest.

+

+ + +

+ <% } %> +

+ + +

+
+
+ Passphrase speichern +
+

Möchtest du deine Passphrase mit dem Server-Admin-Key verschlüsselt auf dem Server gespeichert haben?

+

Dann kann dir der Server-Admin deine Passphrase zuschicken wenn du sie verlegt hast.

+
+

+ + +

+

+ + +

+
+ +
+
+ +