diff options
author | Ed Tanous <ed.tanous@intel.com> | 2018-05-23 01:27:24 +0300 |
---|---|---|
committer | Ed Tanous <ed.tanous@intel.com> | 2018-07-27 01:54:37 +0300 |
commit | 55c7b7a2e58779580f33046d2dd8649243776700 (patch) | |
tree | eed2d032dff3e18c4a8d4778e8f52ae5864620ee /include/token_authorization_middleware.hpp | |
parent | 1752c9657b56a6e1950d8725f44f4298c9872c63 (diff) | |
download | bmcweb-55c7b7a2e58779580f33046d2dd8649243776700.tar.xz |
Move over to upstream c++ style
This patchset moves bmcweb over to the upstream style naming
conventions for variables, classes, and functions, as well as imposes
the latest clang-format file.
This changeset was mostly built automatically by the included
.clang-tidy file, which has the ability to autoformat and auto rename
variables. At some point in the future I would like to see this in
greater use, but for now, we will impose it on bmcweb, and see how it
goes.
Tested: Code still compiles, and appears to run, although other issues
are possible and likely.
Change-Id: If422a2e36df924e897736b3feffa89f411d9dac1
Signed-off-by: Ed Tanous <ed.tanous@intel.com>
Diffstat (limited to 'include/token_authorization_middleware.hpp')
-rw-r--r-- | include/token_authorization_middleware.hpp | 259 |
1 files changed, 127 insertions, 132 deletions
diff --git a/include/token_authorization_middleware.hpp b/include/token_authorization_middleware.hpp index f151e4ff63..fcc86386fa 100644 --- a/include/token_authorization_middleware.hpp +++ b/include/token_authorization_middleware.hpp @@ -12,49 +12,49 @@ namespace crow { -namespace TokenAuthorization { +namespace token_authorization { class Middleware { public: - struct context { - std::shared_ptr<crow::PersistentData::UserSession> session; + struct Context { + std::shared_ptr<crow::persistent_data::UserSession> session; }; - void before_handle(crow::request& req, response& res, context& ctx) { - if (is_on_whitelist(req)) { + void beforeHandle(crow::Request& req, Response& res, Context& ctx) { + if (isOnWhitelist(req)) { return; } - ctx.session = perform_xtoken_auth(req); + ctx.session = performXtokenAuth(req); if (ctx.session == nullptr) { - ctx.session = perform_cookie_auth(req); + ctx.session = performCookieAuth(req); } if (ctx.session == nullptr) { - boost::string_view auth_header = req.get_header_value("Authorization"); - if (!auth_header.empty()) { + boost::string_view authHeader = req.getHeaderValue("Authorization"); + if (!authHeader.empty()) { // Reject any kind of auth other than basic or token - if (boost::starts_with(auth_header, "Token ")) { - ctx.session = perform_token_auth(auth_header); - } else if (boost::starts_with(auth_header, "Basic ")) { - ctx.session = perform_basic_auth(auth_header); + if (boost::starts_with(authHeader, "Token ")) { + ctx.session = performTokenAuth(authHeader); + } else if (boost::starts_with(authHeader, "Basic ")) { + ctx.session = performBasicAuth(authHeader); } } } if (ctx.session == nullptr) { - CROW_LOG_WARNING << "[AuthMiddleware] authorization failed"; + BMCWEB_LOG_WARNING << "[AuthMiddleware] authorization failed"; // If it's a browser connecting, don't send the HTTP authenticate header, // to avoid possible CSRF attacks with basic auth - if (http_helpers::request_prefers_html(req)) { + if (http_helpers::requestPrefersHtml(req)) { res.result(boost::beast::http::status::temporary_redirect); - res.add_header("Location", "/#/login"); + res.addHeader("Location", "/#/login"); } else { res.result(boost::beast::http::status::unauthorized); // only send the WWW-authenticate header if this isn't a xhr from the // browser. most scripts, - if (req.get_header_value("User-Agent").empty()) { - res.add_header("WWW-Authenticate", "Basic"); + if (req.getHeaderValue("User-Agent").empty()) { + res.addHeader("WWW-Authenticate", "Basic"); } } @@ -62,124 +62,122 @@ class Middleware { return; } - // TODO get user privileges here and propagate it via MW context + // TODO get user privileges here and propagate it via MW Context // else let the request continue unharmed } template <typename AllContext> - void after_handle(request& req, response& res, context& ctx, - AllContext& allctx) { + void afterHandle(Request& req, Response& res, Context& ctx, + AllContext& allctx) { // TODO(ed) THis should really be handled by the persistent data // middleware, but because it is upstream, it doesn't have access to the // session information. Should the data middleware persist the current // user session? if (ctx.session != nullptr && ctx.session->persistence == - crow::PersistentData::PersistenceType::SINGLE_REQUEST) { - PersistentData::SessionStore::getInstance().remove_session(ctx.session); + crow::persistent_data::PersistenceType::SINGLE_REQUEST) { + persistent_data::SessionStore::getInstance().removeSession(ctx.session); } } private: - const std::shared_ptr<crow::PersistentData::UserSession> perform_basic_auth( + const std::shared_ptr<crow::persistent_data::UserSession> performBasicAuth( boost::string_view auth_header) const { - CROW_LOG_DEBUG << "[AuthMiddleware] Basic authentication"; + BMCWEB_LOG_DEBUG << "[AuthMiddleware] Basic authentication"; - std::string auth_data; + std::string authData; boost::string_view param = auth_header.substr(strlen("Basic ")); - if (!crow::utility::base64_decode(param, auth_data)) { + if (!crow::utility::base64Decode(param, authData)) { return nullptr; } - std::size_t separator = auth_data.find(':'); + std::size_t separator = authData.find(':'); if (separator == std::string::npos) { return nullptr; } - std::string user = auth_data.substr(0, separator); + std::string user = authData.substr(0, separator); separator += 1; - if (separator > auth_data.size()) { + if (separator > authData.size()) { return nullptr; } - std::string pass = auth_data.substr(separator); + std::string pass = authData.substr(separator); - CROW_LOG_DEBUG << "[AuthMiddleware] Authenticating user: " << user; + BMCWEB_LOG_DEBUG << "[AuthMiddleware] Authenticating user: " << user; - if (!pam_authenticate_user(user, pass)) { + if (!pamAuthenticateUser(user, pass)) { return nullptr; } - // TODO(ed) generate_user_session is a little expensive for basic + // TODO(ed) generateUserSession is a little expensive for basic // auth, as it generates some random identifiers that will never be // used. This should have a "fast" path for when user tokens aren't // needed. // This whole flow needs to be revisited anyway, as we can't be // calling directly into pam for every request - return PersistentData::SessionStore::getInstance().generate_user_session( - user, crow::PersistentData::PersistenceType::SINGLE_REQUEST); + return persistent_data::SessionStore::getInstance().generateUserSession( + user, crow::persistent_data::PersistenceType::SINGLE_REQUEST); } - const std::shared_ptr<crow::PersistentData::UserSession> perform_token_auth( + const std::shared_ptr<crow::persistent_data::UserSession> performTokenAuth( boost::string_view auth_header) const { - CROW_LOG_DEBUG << "[AuthMiddleware] Token authentication"; + BMCWEB_LOG_DEBUG << "[AuthMiddleware] Token authentication"; boost::string_view token = auth_header.substr(strlen("Token ")); auto session = - PersistentData::SessionStore::getInstance().login_session_by_token( - token); + persistent_data::SessionStore::getInstance().loginSessionByToken(token); return session; } - const std::shared_ptr<crow::PersistentData::UserSession> perform_xtoken_auth( - const crow::request& req) const { - CROW_LOG_DEBUG << "[AuthMiddleware] X-Auth-Token authentication"; + const std::shared_ptr<crow::persistent_data::UserSession> performXtokenAuth( + const crow::Request& req) const { + BMCWEB_LOG_DEBUG << "[AuthMiddleware] X-Auth-Token authentication"; - boost::string_view token = req.get_header_value("X-Auth-Token"); + boost::string_view token = req.getHeaderValue("X-Auth-Token"); if (token.empty()) { return nullptr; } auto session = - PersistentData::SessionStore::getInstance().login_session_by_token( - token); + persistent_data::SessionStore::getInstance().loginSessionByToken(token); return session; } - const std::shared_ptr<crow::PersistentData::UserSession> perform_cookie_auth( - const crow::request& req) const { - CROW_LOG_DEBUG << "[AuthMiddleware] Cookie authentication"; + const std::shared_ptr<crow::persistent_data::UserSession> performCookieAuth( + const crow::Request& req) const { + BMCWEB_LOG_DEBUG << "[AuthMiddleware] Cookie authentication"; - boost::string_view cookie_value = req.get_header_value("Cookie"); - if (cookie_value.empty()) { + boost::string_view cookieValue = req.getHeaderValue("Cookie"); + if (cookieValue.empty()) { return nullptr; } - auto start_index = cookie_value.find("SESSION="); - if (start_index == std::string::npos) { + auto startIndex = cookieValue.find("SESSION="); + if (startIndex == std::string::npos) { return nullptr; } - start_index += sizeof("SESSION=") - 1; - auto end_index = cookie_value.find(";", start_index); - if (end_index == std::string::npos) { - end_index = cookie_value.size(); + startIndex += sizeof("SESSION=") - 1; + auto endIndex = cookieValue.find(";", startIndex); + if (endIndex == std::string::npos) { + endIndex = cookieValue.size(); } - boost::string_view auth_key = - cookie_value.substr(start_index, end_index - start_index); + boost::string_view authKey = + cookieValue.substr(startIndex, endIndex - startIndex); - const std::shared_ptr<crow::PersistentData::UserSession> session = - PersistentData::SessionStore::getInstance().login_session_by_token( - auth_key); + const std::shared_ptr<crow::persistent_data::UserSession> session = + persistent_data::SessionStore::getInstance().loginSessionByToken( + authKey); if (session == nullptr) { return nullptr; } #ifndef BMCWEB_INSECURE_DISABLE_CSRF_PREVENTION // RFC7231 defines methods that need csrf protection if (req.method() != "GET"_method) { - boost::string_view csrf = req.get_header_value("X-XSRF-TOKEN"); + boost::string_view csrf = req.getHeaderValue("X-XSRF-TOKEN"); // Make sure both tokens are filled - if (csrf.empty() || session->csrf_token.empty()) { + if (csrf.empty() || session->csrfToken.empty()) { return nullptr; } // Reject if csrf token not available - if (csrf != session->csrf_token) { + if (csrf != session->csrfToken) { return nullptr; } } @@ -188,7 +186,7 @@ class Middleware { } // checks if request can be forwarded without authentication - bool is_on_whitelist(const crow::request& req) const { + bool isOnWhitelist(const crow::Request& req) const { // it's allowed to GET root node without authentica tion if ("GET"_method == req.method()) { if (req.url == "/redfish/v1" || req.url == "/redfish/v1/") { @@ -217,27 +215,27 @@ class Middleware { // routes. // Possibly an init function on first construction? template <typename... Middlewares> -void request_routes(Crow<Middlewares...>& app) { +void requestRoutes(Crow<Middlewares...>& app) { static_assert( - black_magic::contains<PersistentData::Middleware, Middlewares...>::value, - "TokenAuthorization middleware must be enabled in app to use " + black_magic::Contains<persistent_data::Middleware, Middlewares...>::value, + "token_authorization middleware must be enabled in app to use " "auth routes"); - CROW_ROUTE(app, "/login") + BMCWEB_ROUTE(app, "/login") .methods( - "POST"_method)([&](const crow::request& req, crow::response& res) { - boost::string_view content_type = req.get_header_value("content-type"); + "POST"_method)([&](const crow::Request& req, crow::Response& res) { + boost::string_view contentType = req.getHeaderValue("content-type"); boost::string_view username; boost::string_view password; - bool looks_like_ibm = false; + bool looksLikeIbm = false; // This object needs to be declared at this scope so the strings // within it are not destroyed before we can use them - nlohmann::json login_credentials; + nlohmann::json loginCredentials; // Check if auth was provided by a payload - if (content_type == "application/json") { - login_credentials = nlohmann::json::parse(req.body, nullptr, false); - if (login_credentials.is_discarded()) { + if (contentType == "application/json") { + loginCredentials = nlohmann::json::parse(req.body, nullptr, false); + if (loginCredentials.is_discarded()) { res.result(boost::beast::http::status::bad_request); res.end(); return; @@ -245,54 +243,51 @@ void request_routes(Crow<Middlewares...>& app) { // check for username/password in the root object // THis method is how intel APIs authenticate - nlohmann::json::iterator user_it = login_credentials.find("username"); - nlohmann::json::iterator pass_it = login_credentials.find("password"); - if (user_it != login_credentials.end() && - pass_it != login_credentials.end()) { - const std::string* user_str = - user_it->get_ptr<const std::string*>(); - const std::string* pass_str = - pass_it->get_ptr<const std::string*>(); - if (user_str != nullptr && pass_str != nullptr) { - username = *user_str; - password = *pass_str; + nlohmann::json::iterator userIt = loginCredentials.find("username"); + nlohmann::json::iterator passIt = loginCredentials.find("password"); + if (userIt != loginCredentials.end() && + passIt != loginCredentials.end()) { + const std::string* userStr = userIt->get_ptr<const std::string*>(); + const std::string* passStr = passIt->get_ptr<const std::string*>(); + if (userStr != nullptr && passStr != nullptr) { + username = *userStr; + password = *passStr; } } else { // Openbmc appears to push a data object that contains the same // keys (username and password), attempt to use that - auto data_it = login_credentials.find("data"); - if (data_it != login_credentials.end()) { + auto dataIt = loginCredentials.find("data"); + if (dataIt != loginCredentials.end()) { // Some apis produce an array of value ["username", // "password"] - if (data_it->is_array()) { - if (data_it->size() == 2) { - nlohmann::json::iterator user_it2 = data_it->begin(); - nlohmann::json::iterator pass_it2 = data_it->begin() + 1; - looks_like_ibm = true; - if (user_it2 != data_it->end() && - pass_it2 != data_it->end()) { - const std::string* user_str = - user_it2->get_ptr<const std::string*>(); - const std::string* pass_str = - pass_it2->get_ptr<const std::string*>(); - if (user_str != nullptr && pass_str != nullptr) { - username = *user_str; - password = *pass_str; + if (dataIt->is_array()) { + if (dataIt->size() == 2) { + nlohmann::json::iterator userIt2 = dataIt->begin(); + nlohmann::json::iterator passIt2 = dataIt->begin() + 1; + looksLikeIbm = true; + if (userIt2 != dataIt->end() && passIt2 != dataIt->end()) { + const std::string* userStr = + userIt2->get_ptr<const std::string*>(); + const std::string* passStr = + passIt2->get_ptr<const std::string*>(); + if (userStr != nullptr && passStr != nullptr) { + username = *userStr; + password = *passStr; } } } - } else if (data_it->is_object()) { - nlohmann::json::iterator user_it2 = data_it->find("username"); - nlohmann::json::iterator pass_it2 = data_it->find("password"); - if (user_it2 != data_it->end() && pass_it2 != data_it->end()) { - const std::string* user_str = - user_it2->get_ptr<const std::string*>(); - const std::string* pass_str = - pass_it2->get_ptr<const std::string*>(); - if (user_str != nullptr && pass_str != nullptr) { - username = *user_str; - password = *pass_str; + } else if (dataIt->is_object()) { + nlohmann::json::iterator userIt2 = dataIt->find("username"); + nlohmann::json::iterator passIt2 = dataIt->find("password"); + if (userIt2 != dataIt->end() && passIt2 != dataIt->end()) { + const std::string* userStr = + userIt2->get_ptr<const std::string*>(); + const std::string* passStr = + passIt2->get_ptr<const std::string*>(); + if (userStr != nullptr && passStr != nullptr) { + username = *userStr; + password = *passStr; } } } @@ -300,22 +295,22 @@ void request_routes(Crow<Middlewares...>& app) { } } else { // check if auth was provided as a headers - username = req.get_header_value("username"); - password = req.get_header_value("password"); + username = req.getHeaderValue("username"); + password = req.getHeaderValue("password"); } if (!username.empty() && !password.empty()) { - if (!pam_authenticate_user(username, password)) { + if (!pamAuthenticateUser(username, password)) { res.result(boost::beast::http::status::unauthorized); } else { - auto session = PersistentData::SessionStore::getInstance() - .generate_user_session(username); + auto session = persistent_data::SessionStore::getInstance() + .generateUserSession(username); - if (looks_like_ibm) { + if (looksLikeIbm) { // IBM requires a very specific login structure, and doesn't // actually look at the status code. TODO(ed).... Fix that // upstream - res.json_value = { + res.jsonValue = { {"data", "User '" + std::string(username) + "' logged in"}, {"message", "200 OK"}, {"status", "ok"}}; @@ -329,13 +324,13 @@ void request_routes(Crow<Middlewares...>& app) { // "set-cookie" string into the value header, and get the result // we want, even though we are technicaly declaring two headers // here. - res.add_header("Set-Cookie", - "XSRF-TOKEN=" + session->csrf_token + - "; Secure\r\nSet-Cookie: SESSION=" + - session->session_token + "; Secure; HttpOnly"); + res.addHeader("Set-Cookie", + "XSRF-TOKEN=" + session->csrfToken + + "; Secure\r\nSet-Cookie: SESSION=" + + session->sessionToken + "; Secure; HttpOnly"); } else { // if content type is json, assume json token - res.json_value = {{"token", session->session_token}}; + res.jsonValue = {{"token", session->sessionToken}}; } } @@ -345,18 +340,18 @@ void request_routes(Crow<Middlewares...>& app) { res.end(); }); - CROW_ROUTE(app, "/logout") + BMCWEB_ROUTE(app, "/logout") .methods( - "POST"_method)([&](const crow::request& req, crow::response& res) { + "POST"_method)([&](const crow::Request& req, crow::Response& res) { auto& session = - app.template get_context<TokenAuthorization::Middleware>(req) + app.template getContext<token_authorization::Middleware>(req) .session; if (session != nullptr) { - PersistentData::SessionStore::getInstance().remove_session(session); + persistent_data::SessionStore::getInstance().removeSession(session); } res.end(); return; }); } -} // namespace TokenAuthorization +} // namespace token_authorization } // namespace crow |