diff options
Diffstat (limited to 'response.cpp')
-rw-r--r-- | response.cpp | 81 |
1 files changed, 51 insertions, 30 deletions
diff --git a/response.cpp b/response.cpp index 5f4f3f2..9ee1977 100644 --- a/response.cpp +++ b/response.cpp @@ -69,7 +69,39 @@ public: Server& GetServer() const {return m_server; } const Socket& GetSocket() const {return m_server.GetSocket(); } -}; + + // Returns error message, empty on auth success + std::string isAuthenticated() + { + auto& auth{m_path.auth}; + if (auth.size() != 0) { + std::string authorization{m_req[http::field::authorization]}; + if (authorization.substr(0, 6) != "Basic "s) { + return "Bad Authorization Type"; + } + + authorization = authorization.substr(6); + authorization = decode64(authorization); + + size_t pos {authorization.find(':')}; + if (pos == authorization.npos) + return "Bad Authorization Encoding"; + + std::string login{authorization.substr(0, pos)}; + std::string password{authorization.substr(pos + 1)}; + + auto it {auth.find(login)}; + // it.second contains crypted/hash + // password is plain text to validate against the hash + if (it == auth.end() || !Auth::validate(it->second, password)) { + return "Bad Authorization"; + } + } + + return ""; + } + +}; // class RequestContext std::string extend_index_html(std::string path) { @@ -106,6 +138,8 @@ std::string GetServerParam(const std::string& key, Server& server) std::unordered_map<std::string, std::function<std::string(RequestContext&)>> GetRequestParamFunctions{ // following are the supported fields: {"authorization", [](RequestContext& req_ctx) { return std::string{req_ctx.GetReq()[http::field::authorization]}; }}, + + {"is_authenticated", [](RequestContext& req_ctx) { return req_ctx.isAuthenticated() == ""s ? "1"s : "0"s;}}, {"body", [](RequestContext& req_ctx) { return req_ctx.GetReq().body(); }}, @@ -232,6 +266,19 @@ response_type HttpStatusAndStats(std::string status, std::string message, Reques return std::move(res); } +response_type handleAuth(RequestContext& req_ctx, response_type& res) +{ + if (req_ctx.GetPlugin()->has_own_authentication() == false) { + std::string message { req_ctx.isAuthenticated() }; + if (message != "") { + res.set(http::field::www_authenticate, "Basic realm=\"Reichwein.IT Webserver Login\""); + return HttpStatusAndStats("401", message, req_ctx, res); + } + } + + return std::move(res); +} + } // anonymous namespace response_type generate_response(request_type& req, Server& server) @@ -244,35 +291,9 @@ response_type generate_response(request_type& req, Server& server) try { RequestContext req_ctx{req, server}; // can throw std::out_of_range - auto& auth{req_ctx.GetPath().auth}; - if (auth.size() != 0) { - std::string authorization{req[http::field::authorization]}; - if (authorization.substr(0, 6) != "Basic "s) - return HttpStatusAndStats("401", "Bad Authorization Type", req_ctx, res); - - authorization = authorization.substr(6); - authorization = decode64(authorization); - - size_t pos {authorization.find(':')}; - if (pos == authorization.npos) - return HttpStatusAndStats("401", "Bad Authorization Encoding", req_ctx, res); - - std::string login{authorization.substr(0, pos)}; - std::string password{authorization.substr(pos + 1)}; - - auto it {auth.find(login)}; - // it.second contains crypted/hash - // password is plain text to validate against the hash - if (it == auth.end() || !Auth::validate(it->second, password)) { - - // For now, WWW-Authenticate: Basic realm="..." will only be generated for static-files. - // All other plugins are expected to present their own login pages - if (req_ctx.GetPluginName() == "static-files") - res.set(http::field::www_authenticate, "Basic realm=\"Reichwein.IT Webserver Login\""); - - return HttpStatusAndStats("401", "Bad Authorization", req_ctx, res); - } - } + res = handleAuth(req_ctx, res); + if (res.result_int() / 100 == 4) // status 4xx + return res; plugin_type plugin{req_ctx.GetPlugin()}; |