Change ownership of boost::req to crow::req
req is being created later, in the connection life cycle. req was
holding many important values when it was passed to authenticate, so the
authenticate call had to be refactored to includes all the data req was
holding.
Also uses of req before handle have been changed to direct calls to
boot::parse
Tested:
Made a request that did not require authentication
$ curl -vvvv --insecure "https://192.168.7.2:18080/redfish/v1"
Got correct service root
Made a unauthenticated request (Chassis)
$ curl -c cjar -b cjar -k -H "Content-Type: application/json" -X GET https://192.168.7.2:18080/redfish/v1/Chassis
Unauthenticated
Made a log-in request
$ curl -c cjar -b cjar -k -H "Content-Type: application/json" -X POST https://192.168.7.2:18080/login -d "{\"data\": [ \"root\", \"0penBmc\" ] }"
Made (same) Chassis request
$ curl -c cjar -b cjar -k -H "Content-Type: application/json" -X GET https://192.168.7.2:18080/redfish/v1/Chassis
Tested the websockets using scripts/websocket_test.py
Websockets continued to work after this change.
Followed the mTLS instructions here https://github.com/openbmc/docs/blob/master/security/TLS-configuration.md
mTLS continues to work after this change.
Change-Id: I78f78063be0331be00b66349d5d184847add1708
Signed-off-by: John Edward Broadbent <jebr@google.com>
diff --git a/include/authorization.hpp b/include/authorization.hpp
index b1d1097..ecbdca0 100644
--- a/include/authorization.hpp
+++ b/include/authorization.hpp
@@ -93,36 +93,37 @@
BMCWEB_LOG_DEBUG << "[AuthMiddleware] Token authentication";
std::string_view token = authHeader.substr(strlen("Token "));
- auto session =
+ auto sessionOut =
persistent_data::SessionStore::getInstance().loginSessionByToken(token);
- return session;
+ return sessionOut;
}
#endif
#ifdef BMCWEB_ENABLE_XTOKEN_AUTHENTICATION
static std::shared_ptr<persistent_data::UserSession>
- performXtokenAuth(const crow::Request& req)
+ performXtokenAuth(const boost::beast::http::header<true>& reqHeader)
{
BMCWEB_LOG_DEBUG << "[AuthMiddleware] X-Auth-Token authentication";
- std::string_view token = req.getHeaderValue("X-Auth-Token");
+ std::string_view token = reqHeader["X-Auth-Token"];
if (token.empty())
{
return nullptr;
}
- auto session =
+ auto sessionOut =
persistent_data::SessionStore::getInstance().loginSessionByToken(token);
- return session;
+ return sessionOut;
}
#endif
#ifdef BMCWEB_ENABLE_COOKIE_AUTHENTICATION
static std::shared_ptr<persistent_data::UserSession>
- performCookieAuth(const crow::Request& req)
+ performCookieAuth(boost::beast::http::verb method,
+ const boost::beast::http::header<true>& reqHeader)
{
BMCWEB_LOG_DEBUG << "[AuthMiddleware] Cookie authentication";
- std::string_view cookieValue = req.getHeaderValue("Cookie");
+ std::string_view cookieValue = reqHeader["Cookie"];
if (cookieValue.empty())
{
return nullptr;
@@ -142,20 +143,20 @@
std::string_view authKey =
cookieValue.substr(startIndex, endIndex - startIndex);
- std::shared_ptr<persistent_data::UserSession> session =
+ std::shared_ptr<persistent_data::UserSession> sessionOut =
persistent_data::SessionStore::getInstance().loginSessionByToken(
authKey);
- if (session == nullptr)
+ if (sessionOut == nullptr)
{
return nullptr;
}
#ifndef BMCWEB_INSECURE_DISABLE_CSRF_PREVENTION
// RFC7231 defines methods that need csrf protection
- if (req.method() != boost::beast::http::verb::get)
+ if (method != boost::beast::http::verb::get)
{
- std::string_view csrf = req.getHeaderValue("X-XSRF-TOKEN");
+ std::string_view csrf = reqHeader["X-XSRF-TOKEN"];
// Make sure both tokens are filled
- if (csrf.empty() || session->csrfToken.empty())
+ if (csrf.empty() || sessionOut->csrfToken.empty())
{
return nullptr;
}
@@ -165,31 +166,33 @@
return nullptr;
}
// Reject if csrf token not available
- if (!crow::utility::constantTimeStringCompare(csrf, session->csrfToken))
+ if (!crow::utility::constantTimeStringCompare(csrf,
+ sessionOut->csrfToken))
{
return nullptr;
}
}
#endif
- return session;
+ return sessionOut;
}
#endif
#ifdef BMCWEB_ENABLE_MUTUAL_TLS_AUTHENTICATION
static std::shared_ptr<persistent_data::UserSession>
- performTLSAuth(const crow::Request& req, Response& res,
+ performTLSAuth(Response& res,
+ const boost::beast::http::header<true>& reqHeader,
const std::weak_ptr<persistent_data::UserSession>& session)
{
if (auto sp = session.lock())
{
// set cookie only if this is req from the browser.
- if (req.getHeaderValue("User-Agent").empty())
+ if (reqHeader["User-Agent"].empty())
{
BMCWEB_LOG_DEBUG << " TLS session: " << sp->uniqueId
<< " will be used for this request.";
return sp;
}
- std::string_view cookieValue = req.getHeaderValue("Cookie");
+ std::string_view cookieValue = reqHeader["Cookie"];
if (cookieValue.empty() ||
cookieValue.find("SESSION=") == std::string::npos)
{
@@ -211,18 +214,17 @@
#endif
// checks if request can be forwarded without authentication
-static bool isOnWhitelist(const crow::Request& req)
+static bool isOnWhitelist(std::string_view url, boost::beast::http::verb method)
{
- // it's allowed to GET root node without authentication
- if (boost::beast::http::verb::get == req.method())
+ if (boost::beast::http::verb::get == method)
{
- if (req.url == "/redfish/v1" || req.url == "/redfish/v1/" ||
- req.url == "/redfish" || req.url == "/redfish/" ||
- req.url == "/redfish/v1/odata" || req.url == "/redfish/v1/odata/")
+ if (url == "/redfish/v1" || url == "/redfish/v1/" ||
+ url == "/redfish" || url == "/redfish/" ||
+ url == "/redfish/v1/odata" || url == "/redfish/v1/odata/")
{
return true;
}
- if (crow::webroutes::routes.find(std::string(req.url)) !=
+ if (crow::webroutes::routes.find(std::string(url)) !=
crow::webroutes::routes.end())
{
return true;
@@ -231,11 +233,11 @@
// it's allowed to POST on session collection & login without
// authentication
- if (boost::beast::http::verb::post == req.method())
+ if (boost::beast::http::verb::post == method)
{
- if ((req.url == "/redfish/v1/SessionService/Sessions") ||
- (req.url == "/redfish/v1/SessionService/Sessions/") ||
- (req.url == "/login"))
+ if ((url == "/redfish/v1/SessionService/Sessions") ||
+ (url == "/redfish/v1/SessionService/Sessions/") ||
+ (url == "/login"))
{
return true;
}
@@ -244,66 +246,68 @@
return false;
}
-static void authenticate(
- crow::Request& req, Response& res,
- [[maybe_unused]] const std::weak_ptr<persistent_data::UserSession>& session)
+static std::shared_ptr<persistent_data::UserSession> authenticate(
+ std::string_view url, boost::asio::ip::address& ipAddress, Response& res,
+ boost::beast::http::verb method,
+ const boost::beast::http::header<true>& reqHeader,
+ [[maybe_unused]] const std::shared_ptr<persistent_data::UserSession>&
+ session)
{
- if (isOnWhitelist(req))
+ if (isOnWhitelist(url, method))
{
- return;
+ return nullptr;
}
-
const persistent_data::AuthConfigMethods& authMethodsConfig =
persistent_data::SessionStore::getInstance().getAuthMethodsConfig();
+ std::shared_ptr<persistent_data::UserSession> sessionOut = nullptr;
#ifdef BMCWEB_ENABLE_MUTUAL_TLS_AUTHENTICATION
- if (req.session == nullptr && authMethodsConfig.tls)
+ if (authMethodsConfig.tls)
{
- req.session = performTLSAuth(req, res, session);
+ sessionOut = performTLSAuth(res, reqHeader, session);
}
#endif
#ifdef BMCWEB_ENABLE_XTOKEN_AUTHENTICATION
- if (req.session == nullptr && authMethodsConfig.xtoken)
+ if (sessionOut == nullptr && authMethodsConfig.xtoken)
{
- req.session = performXtokenAuth(req);
+ sessionOut = performXtokenAuth(reqHeader);
}
#endif
#ifdef BMCWEB_ENABLE_COOKIE_AUTHENTICATION
- if (req.session == nullptr && authMethodsConfig.cookie)
+ if (sessionOut == nullptr && authMethodsConfig.cookie)
{
- req.session = performCookieAuth(req);
+ sessionOut = performCookieAuth(method, reqHeader);
}
#endif
- if (req.session == nullptr)
+ std::string_view authHeader = reqHeader["Authorization"];
+
+ if (!authHeader.empty())
{
- std::string_view authHeader = req.getHeaderValue("Authorization");
- if (!authHeader.empty())
+ // Reject any kind of auth other than basic or token
+ if (boost::starts_with(authHeader, "Token ") &&
+ authMethodsConfig.sessionToken)
{
- // Reject any kind of auth other than basic or token
- if (boost::starts_with(authHeader, "Token ") &&
- authMethodsConfig.sessionToken)
- {
#ifdef BMCWEB_ENABLE_SESSION_AUTHENTICATION
- req.session = performTokenAuth(authHeader);
+ sessionOut = performTokenAuth(authHeader);
#endif
- }
- else if (boost::starts_with(authHeader, "Basic ") &&
- authMethodsConfig.basic)
- {
+ }
+ else if (boost::starts_with(authHeader, "Basic ") &&
+ authMethodsConfig.basic)
+ {
#ifdef BMCWEB_ENABLE_BASIC_AUTHENTICATION
- req.session = performBasicAuth(req.ipAddress, authHeader);
+ sessionOut = performBasicAuth(ipAddress, authHeader);
#endif
- }
+ }
+ if (sessionOut != nullptr)
+ {
+ return sessionOut;
}
}
-
- if (req.session == nullptr)
- {
- BMCWEB_LOG_WARNING << "[AuthMiddleware] authorization failed";
- forward_unauthorized::sendUnauthorized(req, res);
- res.end();
- return;
- }
+ BMCWEB_LOG_WARNING << "[AuthMiddleware] authorization failed";
+ forward_unauthorized::sendUnauthorized(url, reqHeader["User-Agent"],
+ reqHeader["accept"], res);
+ res.end();
+ return nullptr;
}
} // namespace authorization