#include "PageRequestHandlerFactory.h" #include "Poco/Net/HTTPServerRequest.h" #include "Poco/Net/HTMLForm.h" #include "Poco/DateTime.h" #include "Poco/DateTimeFormatter.h" #include "ConfigPage.h" #include "LoginPage.h" #include "HandleFileRequest.h" #include "DashboardPage.h" #include "CheckEmailPage.h" #include "PassphrasePage.h" #include "SaveKeysPage.h" #include "ElopageWebhook.h" #include "ElopageWebhookLight.h" #include "UserUpdatePasswordPage.h" #include "UserUpdateGroupPage.h" #include "Error500Page.h" #include "CheckTransactionPage.h" #include "ResetPasswordPage.h" #include "RegisterAdminPage.h" #include "DebugPassphrasePage.h" #include "DebugMnemonicPage.h" #include "AdminCheckUserBackupPage.h" #include "TranslatePassphrasePage.h" #include "AdminUserPasswordResetPage.h" #include "RegisterDirectPage.h" #include "AdminGroupsPage.h" #include "DecodeTransactionPage.h" #include "../SingletonManager/SessionManager.h" #include "../lib/Profiler.h" #include "../lib/DataTypeConverter.h" #include "../ServerConfig.h" #include "../Crypto/DRRandom.h" PageRequestHandlerFactory::PageRequestHandlerFactory() : mRemoveGETParameters("^/([a-zA-Z0-9_-]*)"), mLogging(Poco::Logger::get("requestLog")) { ServerConfig::g_ServerKeySeed->put(8, DRRandom::r64()); } Poco::Net::HTTPRequestHandler* PageRequestHandlerFactory::basicSetup(PageRequestMessagedHandler* handler, const Poco::Net::HTTPServerRequest& request, Profiler profiler) { handler->setHost(request.getHost()); handler->setProfiler(profiler); auto login_server_path = request.find("grd-login-server-path"); if (login_server_path != request.end()) { handler->setLoginServerPath("/" + login_server_path->second); } return handler; } Poco::Net::HTTPRequestHandler* PageRequestHandlerFactory::createRequestHandler(const Poco::Net::HTTPServerRequest& request) { //printf("request uri: %s\n", request.getURI().data()); Profiler timeUsed; std::string uri = request.getURI(); std::string url_first_part; std::string dateTimeString = Poco::DateTimeFormatter::format(Poco::DateTime(), "%d.%m.%y %H:%M:%S"); mRemoveGETParameters.extract(uri, url_first_part); std::string externReferer; if (uri != "/favicon.ico") { //printf("[PageRequestHandlerFactory] uri: %s, first part: %s\n", uri.data(), url_first_part.data()); auto referer = request.find("Referer"); auto host = request.find("Host"); if (referer != request.end() && host != request.end()) { //printf("referer: %s\n", referer->second.data()); auto refererString = referer->second; auto hostString = host->second; if (refererString.find(hostString) == refererString.npos) { externReferer = refererString; } }//*/ } if (url_first_part == "/elopage_webhook_261") { mLogging.information(dateTimeString + " call from elopage"); return basicSetup(new ElopageWebhook, request, timeUsed); } if (url_first_part == "/elopage_webhook_211") { mLogging.information(dateTimeString + " call from elopage light"); return basicSetup(new ElopageWebhookLight, request, timeUsed); } // check if user has valid session Poco::Net::NameValueCollection cookies; request.getCookies(cookies); int session_id = 0; try { session_id = atoi(cookies.get("GRADIDO_LOGIN").data()); } catch (...) {} auto sm = SessionManager::getInstance(); auto s = sm->getSession(session_id); // for debugging std::stringstream logStream; auto referer = request.find("Referer"); logStream << dateTimeString << " call " << uri; if (s) {logStream << ", with session: " << std::to_string(s->getHandle()); } if (referer != request.end()) { logStream << ", from: " << referer->second;} mLogging.information(logStream.str()); // end debugging // TODO: count invalid session requests from IP and block IP for some time to prevent brute force session hijacking // or use log file and configure fail2ban for this to do if (url_first_part == "/checkEmail") { //return new CheckEmailPage(s); //printf("url checkEmail\n"); // if (!s) { return handleCheckEmail(s, uri, request, timeUsed); // } //printf("skip handleCheckEmail\n"); } /*if (url_first_part == "/register") { auto pageRequestHandler = new RegisterPage; pageRequestHandler->setProfiler(timeUsed); return pageRequestHandler; }*/ if (url_first_part.size() >= 9 && url_first_part.substr(0,9) == "/register") { //if (url_first_part == "/register" || url_first_part == "/registerDirect" ) { return basicSetup(new RegisterDirectPage, request, timeUsed); } if (url_first_part == "/resetPassword") { return basicSetup(new ResetPasswordPage, request, timeUsed); } if (url_first_part == "/decode_transaction") { mLogging.information(dateTimeString + " decode"); return basicSetup(new DecodeTransactionPage(s), request, timeUsed); } if (s) { if (externReferer != "") { s->setLastReferer(externReferer); } model::table::User* userModel = nullptr; auto newUser = s->getNewUser(); if (newUser) userModel = newUser->getModel(); if (s->errorCount() || (userModel && userModel->errorCount())) { if (userModel && userModel->errorCount()) { s->getErrors(userModel); } s->sendErrorsAsEmail(); return basicSetup(new Error500Page(s), request, timeUsed); } if (url_first_part == "/error500") { return basicSetup(new Error500Page(s), request, timeUsed); } if (url_first_part == "/userUpdateGroup") { return basicSetup(new UserUpdateGroupPage(s), request, timeUsed); } if (url_first_part == "/transform_passphrase") { return basicSetup(new TranslatePassphrasePage(s), request, timeUsed); } if (userModel && userModel->getRole() == model::table::ROLE_ADMIN) { if (url_first_part == "/adminRegister") { return basicSetup(new RegisterAdminPage(s), request, timeUsed); } if (url_first_part == "/debugPassphrase") { return basicSetup(new DebugPassphrasePage(s), request, timeUsed); } if (url_first_part == "/debugMnemonic") { return basicSetup(new DebugMnemonicPage(s), request, timeUsed); } if (url_first_part == "/checkUserBackups") { return basicSetup(new AdminCheckUserBackupPage(s), request, timeUsed); } if (url_first_part == "/adminUserPasswordReset") { return basicSetup(new AdminUserPasswordResetPage(s), request, timeUsed); } if (url_first_part == "/groups") { return basicSetup(new AdminGroupsPage(s), request, timeUsed); } } if(url_first_part == "/logout") { sm->releaseSession(s); // remove cookie(s) //printf("session released\n"); return basicSetup(new LoginPage(nullptr), request, timeUsed); } if(url_first_part == "/user_delete") { if(s->deleteUser()) { sm->releaseSession(s); return basicSetup(new LoginPage(nullptr), request, timeUsed); } } auto sessionState = s->getSessionState(); //printf("session state: %s\n", s->getSessionStateString()); if (url_first_part == "/updateUserPassword") { return basicSetup(new UserUpdatePasswordPage(s), request, timeUsed); } if (url_first_part == "/checkTransactions") { return basicSetup(new CheckTransactionPage(s), request, timeUsed); } if(s && newUser && newUser->hasPassword() && newUser->hasPublicKey()) { //printf("[PageRequestHandlerFactory] go to dashboard page with user\n"); return basicSetup(new DashboardPage(s), request, timeUsed); } if (url_first_part == "/login" || url_first_part == "/") { return basicSetup(new LoginPage(s), request, timeUsed); } } else { if (url_first_part == "/config") { return new ConfigPage; } else if (url_first_part == "/login") { return basicSetup(new LoginPage(nullptr), request, timeUsed); } } return basicSetup(new LoginPage(nullptr), request, timeUsed); //return new HandleFileRequest; //return new PageRequestHandlerFactory; } Poco::Net::HTTPRequestHandler* PageRequestHandlerFactory::handleCheckEmail(Session* session, const std::string uri, const Poco::Net::HTTPServerRequest& request, Profiler timeUsed) { Poco::Net::HTMLForm form(request); unsigned long long verificationCode = 0; Languages lang = LANG_DE; // if verification code is valid, go to next page, passphrase // login via verification code, if no session is active // try to get code from form get parameter if (!form.empty()) { try { verificationCode = stoull(form.get("email-verification-code", "0")); } catch (...) {} lang = LanguageManager::languageFromString(form.get("lang-btn", "de")); } // try to get code from uri parameter if (!verificationCode) { size_t pos = uri.find_last_of("/"); auto str = uri.substr(pos + 1); DataTypeConverter::strToInt(str, verificationCode); } // if no verification code given or error with given code, show form if (!verificationCode) { return basicSetup(new CheckEmailPage(session), request, timeUsed); } // we have a verification code, now let's check that thing auto sm = SessionManager::getInstance(); // no session or active session don't belong to verification code if (!session || session->getEmailVerificationCode() != verificationCode) { //sm->releaseSession(session); //session = nullptr; // it is maybe unsafe session = sm->findByEmailVerificationCode(verificationCode); } // no suitable session in memory, try to create one from db data if (!session) { session = sm->getNewSession(); session->setLanguage(lang); if (session->loadFromEmailVerificationCode(verificationCode)) { // login not possible in this function, forwarded to PassphrasePage /*auto cookie_id = session->getHandle(); auto user_host = request.clientAddress().host(); session->setClientIp(user_host); response.addCookie(Poco::Net::HTTPCookie("user", std::to_string(cookie_id))); */ } else { //sm->releaseSession(session); return basicSetup(new CheckEmailPage(session), request, timeUsed); } } // suitable session found or created if (session) { auto user_host = request.clientAddress().host(); session->setClientIp(user_host); assert(session->getNewUser()); if (!session->getNewUser()->hasPassword()) { // user has no password, maybe account created from elopage webhook return basicSetup(new UserUpdatePasswordPage(session), request, timeUsed); } /* //! \return 1 = konto already exist //! -1 = invalid code //! -2 = critical error //! 0 = ok */ // update session, mark as verified int retUpdateEmailVerification = session->updateEmailVerification(verificationCode); printf("[%s] return from update email verification: %d\n", __FUNCTION__, retUpdateEmailVerification); if (0 == retUpdateEmailVerification) { //printf("[PageRequestHandlerFactory::handleCheckEmail] timeUsed: %s\n", timeUsed.string().data()); SessionHTTPRequestHandler* pageRequestHandler = nullptr; if (model::table::EMAIL_OPT_IN_REGISTER_DIRECT == session->getEmailVerificationType()) { printf("return check email page\n"); pageRequestHandler = new CheckEmailPage(session); } else if(SESSION_STATE_RESET_PASSWORD_REQUEST == session->getSessionState()) { pageRequestHandler = new UserUpdatePasswordPage(session); } else { pageRequestHandler = new PassphrasePage(session); } return basicSetup(pageRequestHandler, request, timeUsed); } else if (1 == retUpdateEmailVerification) { //auto user = session->getUser(); //LoginPage* loginPage = new LoginPage(session); //loginPage->setProfiler(timeUsed); return basicSetup(new CheckEmailPage(session), request, timeUsed); } else if (-1 == retUpdateEmailVerification) { auto checkEmail = new CheckEmailPage(session); checkEmail->getErrors(session); sm->releaseSession(session); return basicSetup(checkEmail, request, timeUsed); } else if (-2 == retUpdateEmailVerification) { return basicSetup(new Error500Page(session), request, timeUsed); } } if (session) { sm->releaseSession(session); } return basicSetup(new CheckEmailPage(nullptr), request, timeUsed); }