diff --git a/handlers/handlerlogin.cpp b/handlers/handlerlogin.cpp index 12722cb..a91707d 100644 --- a/handlers/handlerlogin.cpp +++ b/handlers/handlerlogin.cpp @@ -20,53 +20,9 @@ SOFTWARE. */ #include #include -#include #include "handlerlogin.h" #include "../logger.h" -struct LoginFail -{ - std::mutex mutex; - std::atomic count; - time_t lastfail; -}; -static std::map loginFails; - -// TODO: make configurable -bool HandlerLogin::isBanned(std::string ip) -{ - if(utils::hasKey(loginFails, ip)) - { - LoginFail &fl = loginFails[ip]; - std::lock_guard lock(fl.mutex); - return fl.count > 5 && (time(nullptr) - fl.lastfail) < 1200; - } - return false; -} - -void HandlerLogin::incFailureCount(std::string ip) -{ - LoginFail &fl = loginFails[ip]; - fl.count += 1; - fl.lastfail = time(nullptr); -} - -std::vector HandlerLogin::pbkdf5(std::string password, const std::vector &salt) -{ - unsigned char hash[32]; - const EVP_MD *sha256 = EVP_sha256(); - const unsigned char *rawsalt = reinterpret_cast(salt.data()); - PKCS5_PBKDF2_HMAC(password.c_str(), password.size(), rawsalt, salt.size(), 300000, sha256, sizeof(hash), hash); - - std::vector result; - - for(size_t i = 0; i < sizeof(hash); i++) - { - - result.push_back(static_cast(hash[i])); - } - - return result; -} +#include "../authenticator.h" Response HandlerLogin::handleRequest(const Request &r) { @@ -74,48 +30,35 @@ Response HandlerLogin::handleRequest(const Request &r) return errorResponse("Login error", "The supplied credentials are incorrect"); }; - if(isBanned(r.getIp())) - { - return errorResponse("Banned", "You have been banned for too many login attempts. Try again later"); - } if(r.param("submit") == "1") { std::string password = r.post("password"); std::string username = r.post("user"); auto userDao = this->database->createUserDao(); - std::optional user = userDao->find(username); - if(!user) + Authenticator authenticator(*userDao); + + std::variant authresult = authenticator.authenticate(username, password, r.getIp()); + if(std::holds_alternative(authresult)) { - return createErrorReesponse(); + User user = std::get(authresult); + *(this->userSession) = Session(user); + Response r = Response::redirectTemporarily(urlProvider->index()); + return r; } - if(!user->enabled) + AuthenticationError error = std::get(authresult); + if(error == AuthenticationError::UserDisabled) { return errorResponse("Login failed", "The user account has been disabled"); } - auto hashresult = pbkdf5(password, user.value().salt); - // TODO: timing attack - if(hashresult == user.value().password) - { - loginFails.erase(r.getIp()); - Response r = Response::redirectTemporarily(urlProvider->index()); - *(this->userSession) = Session(user.value()); - return r; - } - else - { - // TODO: only if wanted by config - incFailureCount(r.getIp()); - return createErrorReesponse(); - } - - // auto pbkdf5 = pbkdf5(password, user->) + return errorResponse("Login failed", "Login with supplied credentials failed"); } std::string page = r.get("page"); if(page.empty()) + { page = "index"; - + } TemplatePage &loginTemplatePage = this->templ->getPage("login"); setGeneralVars(loginTemplatePage); loginTemplatePage.setVar("loginurl", urlProvider->login(page)); @@ -123,6 +66,7 @@ Response HandlerLogin::handleRequest(const Request &r) Response result; result.setStatus(200); result.setBody(loginTemplatePage.render()); + return result; } diff --git a/handlers/handlerlogin.h b/handlers/handlerlogin.h index 5e3c029..35a12eb 100644 --- a/handlers/handlerlogin.h +++ b/handlers/handlerlogin.h @@ -5,11 +5,6 @@ class HandlerLogin : public Handler { - private: - bool isBanned(std::string ip); - void incFailureCount(std::string ip); - std::vector pbkdf5(std::string password, const std::vector &salt); - public: HandlerLogin(); Response handleRequest(const Request &r) override;