summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorEd Tanous <ed.tanous@intel.com>2018-03-28 03:41:04 +0300
committerEd Tanous <ed.tanous@intel.com>2018-06-29 21:18:14 +0300
commite0d918bc397350aa21af3dab9faa6e21748f6373 (patch)
treebdc13d1e9937c0f153e89f3ab1be050d4bf52ee7 /include
parent77dd8813e9a1f2baec63d959de15af39a8cd12d0 (diff)
downloadbmcweb-e0d918bc397350aa21af3dab9faa6e21748f6373.tar.xz
Boost beast
This commit is the beginings of attempting to transition away from crow, and toward boost::beast. Unit tests are passing, and implementation appears to be slightly faster than crow. Change-Id: Ic8d946dc7a04f514c67b1098f181eee1ced69171
Diffstat (limited to 'include')
-rw-r--r--include/ast_video_puller.hpp2
-rw-r--r--include/openbmc_dbus_rest.hpp45
-rw-r--r--include/pam_authenticate.hpp13
-rw-r--r--include/persistent_data_middleware.hpp8
-rw-r--r--include/redfish_v1.hpp36
-rw-r--r--include/sessions.hpp59
-rw-r--r--include/token_authorization_middleware.hpp187
-rw-r--r--include/webassets.hpp8
8 files changed, 175 insertions, 183 deletions
diff --git a/include/ast_video_puller.hpp b/include/ast_video_puller.hpp
index 759aaebb00..6cd7f37c35 100644
--- a/include/ast_video_puller.hpp
+++ b/include/ast_video_puller.hpp
@@ -148,7 +148,7 @@ class AsyncVideoPuller {
boost::asio::async_read(
dev_video, mutable_buffer, [this](const boost::system::error_code &ec,
std::size_t bytes_transferred) {
- if (ec != nullptr) {
+ if (ec) {
std::cerr << "Read failed with status " << ec << "\n";
} else {
this->read_done();
diff --git a/include/openbmc_dbus_rest.hpp b/include/openbmc_dbus_rest.hpp
index 4257127c81..e6052f13b5 100644
--- a/include/openbmc_dbus_rest.hpp
+++ b/include/openbmc_dbus_rest.hpp
@@ -2,6 +2,7 @@
#include <tinyxml2.h>
#include <dbus_singleton.hpp>
+#include <boost/algorithm/string.hpp>
#include <boost/container/flat_set.hpp>
namespace crow {
@@ -130,7 +131,7 @@ void handle_enumerate(crow::response &res, const std::string &object_path) {
const boost::system::error_code ec,
const GetSubTreeType &object_names) {
if (ec) {
- res.code = 500;
+ res.result(boost::beast::http::status::internal_server_error);
res.end();
return;
}
@@ -144,7 +145,7 @@ void handle_enumerate(crow::response &res, const std::string &object_path) {
}
if (connections.size() <= 0) {
- res.code = 404;
+ res.result(boost::beast::http::status::not_found);
res.end();
return;
}
@@ -163,10 +164,10 @@ void handle_enumerate(crow::response &res, const std::string &object_path) {
template <typename... Middlewares>
void request_routes(Crow<Middlewares...> &app) {
- CROW_ROUTE(app, "/bus/").methods("GET"_method)([](const crow::request &req) {
- return nlohmann::json{{"busses", {{{"name", "system"}}}}, {"status", "ok"}};
-
- });
+ CROW_ROUTE(app, "/bus/")
+ .methods("GET"_method)([](const crow::request &req, crow::response &res) {
+ res.json_value = {{"busses", {{{"name", "system"}}}}, {"status", "ok"}};
+ });
CROW_ROUTE(app, "/bus/system/")
.methods("GET"_method)([](const crow::request &req, crow::response &res) {
@@ -174,7 +175,7 @@ void request_routes(Crow<Middlewares...> &app) {
auto myCallback = [&res](const boost::system::error_code ec,
std::vector<std::string> &names) {
if (ec) {
- res.code = 500;
+ res.result(boost::beast::http::status::internal_server_error);
} else {
std::sort(names.begin(), names.end());
nlohmann::json j{{"status", "ok"}};
@@ -197,7 +198,7 @@ void request_routes(Crow<Middlewares...> &app) {
[&res](const boost::system::error_code ec,
const std::vector<std::string> &object_paths) {
if (ec) {
- res.code = 500;
+ res.result(boost::beast::http::status::internal_server_error);
} else {
res.json_value = {{"status", "ok"},
{"message", "200 OK"},
@@ -232,21 +233,21 @@ void request_routes(Crow<Middlewares...> &app) {
auto request_dbus_data =
nlohmann::json::parse(req.body, nullptr, false);
if (request_dbus_data.is_discarded()) {
- res.code = 400;
+ res.result(boost::beast::http::status::unauthorized);
res.end();
return;
}
auto property_value_it = request_dbus_data.find("data");
if (property_value_it == request_dbus_data.end()) {
- res.code = 400;
+ res.result(boost::beast::http::status::unauthorized);
res.end();
return;
}
property_set_value = property_value_it->get<const std::string>();
if (property_set_value.empty()) {
- res.code = 400;
+ res.result(boost::beast::http::status::unauthorized);
res.end();
return;
}
@@ -266,16 +267,16 @@ void request_routes(Crow<Middlewares...> &app) {
](const boost::system::error_code ec,
const GetObjectType &object_names) {
if (ec) {
- res.code = 500;
+ res.result(boost::beast::http::status::internal_server_error);
res.end();
return;
}
if (object_names.size() != 1) {
- res.code = 404;
+ res.result(boost::beast::http::status::not_found);
res.end();
return;
}
- if (req.method == "GET"_method) {
+ if (req.method() == "GET"_method) {
for (auto &interface : object_names[0].second) {
crow::connections::system_bus->async_method_call(
[&res, transaction](
@@ -303,7 +304,7 @@ void request_routes(Crow<Middlewares...> &app) {
object_names[0].first, object_path,
"org.freedesktop.DBus.Properties", "GetAll", interface);
}
- } else if (req.method == "PUT"_method) {
+ } else if (req.method() == "PUT"_method) {
for (auto &interface : object_names[0].second) {
crow::connections::system_bus->async_method_call(
[
@@ -351,7 +352,7 @@ void request_routes(Crow<Middlewares...> &app) {
// if nobody filled in the property, all calls either
// errored, or failed
if (transaction == nullptr) {
- res.code = 403;
+ res.result(boost::beast::http::status::forbidden);
res.json_value = {{"status", "error"},
{"message", "403 Forbidden"},
{"data",
@@ -426,7 +427,7 @@ void request_routes(Crow<Middlewares...> &app) {
if (it != strs.end()) {
// if there is more levels past the method name, something went
// wrong, throw an error
- res.code = 404;
+ res.result(boost::beast::http::status::not_found);
res.end();
return;
}
@@ -452,8 +453,9 @@ void request_routes(Crow<Middlewares...> &app) {
CROW_LOG_ERROR << "XML document failed to parse "
<< process_name << " " << object_path
<< "\n";
- res.write(nlohmann::json{{"status", "XML parse error"}});
- res.code = 500;
+ res.json_value = {{"status", "XML parse error"}};
+ res.result(
+ boost::beast::http::status::internal_server_error);
} else {
nlohmann::json interfaces_array = nlohmann::json::array();
tinyxml2::XMLElement *interface =
@@ -498,7 +500,8 @@ void request_routes(Crow<Middlewares...> &app) {
CROW_LOG_ERROR << "XML document failed to parse "
<< process_name << " " << object_path
<< "\n";
- res.code = 500;
+ res.result(
+ boost::beast::http::status::internal_server_error);
} else {
tinyxml2::XMLElement *node =
@@ -575,7 +578,7 @@ void request_routes(Crow<Middlewares...> &app) {
if (interface == nullptr) {
// if we got to the end of the list and never found a
// match, throw 404
- res.code = 404;
+ res.result(boost::beast::http::status::not_found);
}
}
}
diff --git a/include/pam_authenticate.hpp b/include/pam_authenticate.hpp
index 5b4b454ab4..997c2974bd 100644
--- a/include/pam_authenticate.hpp
+++ b/include/pam_authenticate.hpp
@@ -1,8 +1,9 @@
#pragma once
#include <security/pam_appl.h>
-#include <memory>
#include <cstring>
+#include <memory>
+#include <boost/utility/string_view.hpp>
// function used to get user input
inline int pam_function_conversation(int num_msg,
@@ -32,13 +33,15 @@ inline int pam_function_conversation(int num_msg,
return PAM_SUCCESS;
}
-inline bool pam_authenticate_user(const std::string& username,
- const std::string& password) {
+inline bool pam_authenticate_user(const boost::string_view username,
+ const boost::string_view password) {
+ std::string user_str(username);
+ std::string pass_str(password);
const struct pam_conv local_conversation = {
- pam_function_conversation, const_cast<char*>(password.c_str())};
+ pam_function_conversation, const_cast<char*>(pass_str.c_str())};
pam_handle_t* local_auth_handle = NULL; // this gets set by pam_start
- if (pam_start("dropbear", username.c_str(), &local_conversation,
+ if (pam_start("dropbear", user_str.c_str(), &local_conversation,
&local_auth_handle) != PAM_SUCCESS) {
return false;
}
diff --git a/include/persistent_data_middleware.hpp b/include/persistent_data_middleware.hpp
index fcab52fa61..77a5bbbf0a 100644
--- a/include/persistent_data_middleware.hpp
+++ b/include/persistent_data_middleware.hpp
@@ -68,11 +68,11 @@ class Middleware {
if (jSessions != data.end()) {
if (jSessions->is_object()) {
for (const auto& elem : *jSessions) {
- UserSession newSession;
+ std::shared_ptr<UserSession> newSession = std::make_shared<UserSession>();
- if (newSession.fromJson(elem)) {
- session_store->auth_tokens.emplace(newSession.unique_id,
- std::move(newSession));
+ if (newSession->fromJson(elem)) {
+ session_store->auth_tokens.emplace(newSession->unique_id,
+ newSession);
}
}
}
diff --git a/include/redfish_v1.hpp b/include/redfish_v1.hpp
index 49a5a15e81..e8f4d7fd35 100644
--- a/include/redfish_v1.hpp
+++ b/include/redfish_v1.hpp
@@ -11,36 +11,6 @@
namespace crow {
namespace redfish {
-template <typename... Middlewares>
-void get_redfish_sub_routes(Crow<Middlewares...>& app, const std::string& url,
- nlohmann::json& j) {
- std::vector<const std::string*> routes = app.get_routes(url);
- for (auto route : routes) {
- auto redfish_sub_route =
- route->substr(url.size(), route->size() - url.size() - 1);
- // check if the route is at this level, and we didn't find and exact match
- // also, filter out resources that start with $ to remove $metadata
- if (!redfish_sub_route.empty() && redfish_sub_route[0] != '$' &&
- redfish_sub_route.find('/') == std::string::npos) {
- j[redfish_sub_route] = nlohmann::json{{"@odata.id", *route}};
- }
- }
-}
-
-std::string execute_process(const char* cmd) {
- std::array<char, 128> buffer;
- std::string result;
- std::shared_ptr<FILE> pipe(popen(cmd, "r"), pclose);
- if (!pipe) throw std::runtime_error("popen() failed!");
- while (!feof(pipe.get())) {
- if (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr)
- result += buffer.data();
- }
- return result;
-}
-
-// GetManagedObjects unpack type. Observe that variant has only one bool type,
-// because we don't actually use the values it provides
using ManagedObjectType = std::vector<std::pair<
sdbusplus::message::object_path,
boost::container::flat_map<
@@ -62,7 +32,7 @@ void request_routes(Crow<Middlewares...>& app) {
[&](const boost::system::error_code ec,
const ManagedObjectType& users) {
if (ec) {
- res.code = 500;
+ res.result(boost::beast::http::status::internal_server_error);
} else {
res.json_value = {
{"@odata.context",
@@ -107,7 +77,7 @@ void request_routes(Crow<Middlewares...>& app) {
const boost::system::error_code ec,
const ManagedObjectType& users) {
if (ec) {
- res.code = 500;
+ res.result(boost::beast::http::status::internal_server_error);
} else {
for (auto& user : users) {
const std::string& path =
@@ -141,7 +111,7 @@ void request_routes(Crow<Middlewares...>& app) {
}
}
if (res.json_value.is_null()) {
- res.code = 404;
+ res.result(boost::beast::http::status::not_found);
}
}
res.end();
diff --git a/include/sessions.hpp b/include/sessions.hpp
index 15ff9cad38..fdd12000f4 100644
--- a/include/sessions.hpp
+++ b/include/sessions.hpp
@@ -73,12 +73,12 @@ struct UserSession {
}
};
-void to_json(nlohmann::json& j, const UserSession& p) {
- if (p.persistence != PersistenceType::SINGLE_REQUEST) {
- j = nlohmann::json{{"unique_id", p.unique_id},
- {"session_token", p.session_token},
- {"username", p.username},
- {"csrf_token", p.csrf_token}};
+void to_json(nlohmann::json& j, const std::shared_ptr<UserSession> p) {
+ if (p->persistence != PersistenceType::SINGLE_REQUEST) {
+ j = {{"unique_id", p->unique_id},
+ {"session_token", p->session_token},
+ {"username", p->username},
+ {"csrf_token", p->csrf_token}};
}
}
@@ -87,8 +87,8 @@ class Middleware;
class SessionStore {
public:
SessionStore() : timeout_in_minutes(60) {}
- const UserSession& generate_user_session(
- const std::string& username,
+ std::shared_ptr<UserSession> generate_user_session(
+ const boost::string_view username,
PersistenceType persistence = PersistenceType::TIMEOUT) {
// TODO(ed) find a secure way to not generate session identifiers if
// persistence is set to SINGLE_REQUEST
@@ -120,42 +120,42 @@ class SessionStore {
for (int i = 0; i < unique_id.size(); ++i) {
unique_id[i] = alphanum[dist(rd)];
}
-
- const auto session_it = auth_tokens.emplace(
- session_token,
- std::move(UserSession{unique_id, session_token, username, csrf_token,
- std::chrono::steady_clock::now(), persistence}));
- const UserSession& user = (session_it).first->second;
+ auto session = std::make_shared<UserSession>(
+ UserSession{unique_id, session_token, std::string(username), csrf_token,
+ std::chrono::steady_clock::now(), persistence});
+ auto it = auth_tokens.emplace(std::make_pair(session_token, session));
// Only need to write to disk if session isn't about to be destroyed.
need_write_ = persistence == PersistenceType::TIMEOUT;
- return user;
+ return it.first->second;
}
- const UserSession* login_session_by_token(const std::string& token) {
+ std::shared_ptr<UserSession> login_session_by_token(
+ const boost::string_view token) {
apply_session_timeouts();
- auto session_it = auth_tokens.find(token);
+ auto session_it = auth_tokens.find(std::string(token));
if (session_it == auth_tokens.end()) {
return nullptr;
}
- UserSession& foo = session_it->second;
- foo.last_updated = std::chrono::steady_clock::now();
- return &foo;
+ std::shared_ptr<UserSession> user_session = session_it->second;
+ user_session->last_updated = std::chrono::steady_clock::now();
+ return user_session;
}
- const UserSession* get_session_by_uid(const std::string& uid) {
+ std::shared_ptr<UserSession> get_session_by_uid(
+ const boost::string_view uid) {
apply_session_timeouts();
// TODO(Ed) this is inefficient
auto session_it = auth_tokens.begin();
while (session_it != auth_tokens.end()) {
- if (session_it->second.unique_id == uid) {
- return &session_it->second;
+ if (session_it->second->unique_id == uid) {
+ return session_it->second;
}
session_it++;
}
return nullptr;
}
- void remove_session(const UserSession* session) {
+ void remove_session(std::shared_ptr<UserSession> session) {
auth_tokens.erase(session->session_token);
need_write_ = true;
}
@@ -168,8 +168,8 @@ class SessionStore {
std::vector<const std::string*> ret;
ret.reserve(auth_tokens.size());
for (auto& session : auth_tokens) {
- if (getAll || type == session.second.persistence) {
- ret.push_back(&session.second.unique_id);
+ if (getAll || type == session.second->persistence) {
+ ret.push_back(&session.second->unique_id);
}
}
return ret;
@@ -191,7 +191,7 @@ class SessionStore {
last_timeout_update = time_now;
auto auth_tokens_it = auth_tokens.begin();
while (auth_tokens_it != auth_tokens.end()) {
- if (time_now - auth_tokens_it->second.last_updated >=
+ if (time_now - auth_tokens_it->second->last_updated >=
timeout_in_minutes) {
auth_tokens_it = auth_tokens.erase(auth_tokens_it);
need_write_ = true;
@@ -202,11 +202,12 @@ class SessionStore {
}
}
std::chrono::time_point<std::chrono::steady_clock> last_timeout_update;
- boost::container::flat_map<std::string, UserSession> auth_tokens;
+ boost::container::flat_map<std::string, std::shared_ptr<UserSession>>
+ auth_tokens;
std::random_device rd;
bool need_write_{false};
std::chrono::minutes timeout_in_minutes;
};
-} // namespaec PersistentData
+} // namespace PersistentData
} // namespace crow
diff --git a/include/token_authorization_middleware.hpp b/include/token_authorization_middleware.hpp
index 07540d42b0..49649dd978 100644
--- a/include/token_authorization_middleware.hpp
+++ b/include/token_authorization_middleware.hpp
@@ -5,10 +5,9 @@
#include <webassets.hpp>
#include <random>
#include <crow/app.h>
-#include <crow/http_codes.h>
+#include <crow/common.h>
#include <crow/http_request.h>
#include <crow/http_response.h>
-#include <boost/bimap.hpp>
#include <boost/container/flat_set.hpp>
namespace crow {
@@ -18,7 +17,7 @@ namespace TokenAuthorization {
class Middleware {
public:
struct context {
- const crow::PersistentData::UserSession* session;
+ std::shared_ptr<crow::PersistentData::UserSession> session;
};
void before_handle(crow::request& req, response& res, context& ctx) {
@@ -27,25 +26,27 @@ class Middleware {
}
ctx.session = perform_xtoken_auth(req);
-
if (ctx.session == nullptr) {
ctx.session = perform_cookie_auth(req);
}
-
- const std::string& auth_header = req.get_header_value("Authorization");
- // Reject any kind of auth other than basic or token
- if (ctx.session == nullptr && boost::starts_with(auth_header, "Token ")) {
- ctx.session = perform_token_auth(auth_header);
- }
-
- if (ctx.session == nullptr && boost::starts_with(auth_header, "Basic ")) {
- ctx.session = perform_basic_auth(auth_header);
+ if (ctx.session == nullptr) {
+ boost::string_view auth_header = req.get_header_value("Authorization");
+ if (!auth_header.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 (ctx.session == nullptr) {
CROW_LOG_WARNING << "[AuthMiddleware] authorization failed";
- res.code = static_cast<int>(HttpRespCode::UNAUTHORIZED);
+
+ res.result(boost::beast::http::status::unauthorized);
res.add_header("WWW-Authenticate", "Basic");
+
res.end();
return;
}
@@ -57,10 +58,10 @@ class Middleware {
template <typename AllContext>
void after_handle(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?
+ // 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) {
@@ -69,12 +70,12 @@ class Middleware {
}
private:
- const crow::PersistentData::UserSession* perform_basic_auth(
- const std::string& auth_header) const {
+ const std::shared_ptr<crow::PersistentData::UserSession> perform_basic_auth(
+ boost::string_view auth_header) const {
CROW_LOG_DEBUG << "[AuthMiddleware] Basic authentication";
std::string auth_data;
- std::string param = auth_header.substr(strlen("Basic "));
+ boost::string_view param = auth_header.substr(strlen("Basic "));
if (!crow::utility::base64_decode(param, auth_data)) {
return nullptr;
}
@@ -102,24 +103,24 @@ class Middleware {
// needed.
// This whole flow needs to be revisited anyway, as we can't be
// calling directly into pam for every request
- return &(PersistentData::session_store->generate_user_session(
- user, crow::PersistentData::PersistenceType::SINGLE_REQUEST));
+ return PersistentData::session_store->generate_user_session(
+ user, crow::PersistentData::PersistenceType::SINGLE_REQUEST);
}
- const crow::PersistentData::UserSession* perform_token_auth(
- const std::string& auth_header) const {
+ const std::shared_ptr<crow::PersistentData::UserSession> perform_token_auth(
+ boost::string_view auth_header) const {
CROW_LOG_DEBUG << "[AuthMiddleware] Token authentication";
- std::string token = auth_header.substr(strlen("Token "));
+ boost::string_view token = auth_header.substr(strlen("Token "));
auto session = PersistentData::session_store->login_session_by_token(token);
return session;
}
- const crow::PersistentData::UserSession* perform_xtoken_auth(
+ 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::string& token = req.get_header_value("X-Auth-Token");
+ boost::string_view token = req.get_header_value("X-Auth-Token");
if (token.empty()) {
return nullptr;
}
@@ -127,11 +128,11 @@ class Middleware {
return session;
}
- const crow::PersistentData::UserSession* perform_cookie_auth(
+ const std::shared_ptr<crow::PersistentData::UserSession> perform_cookie_auth(
const crow::request& req) const {
CROW_LOG_DEBUG << "[AuthMiddleware] Cookie authentication";
- auto& cookie_value = req.get_header_value("Cookie");
+ boost::string_view cookie_value = req.get_header_value("Cookie");
if (cookie_value.empty()) {
return nullptr;
}
@@ -145,18 +146,18 @@ class Middleware {
if (end_index == std::string::npos) {
end_index = cookie_value.size();
}
- std::string auth_key =
+ boost::string_view auth_key =
cookie_value.substr(start_index, end_index - start_index);
- const crow::PersistentData::UserSession* session =
+ const std::shared_ptr<crow::PersistentData::UserSession> session =
PersistentData::session_store->login_session_by_token(auth_key);
if (session == nullptr) {
return nullptr;
}
// RFC7231 defines methods that need csrf protection
- if (req.method != "GET"_method) {
- const std::string& csrf = req.get_header_value("X-XSRF-TOKEN");
+ if (req.method() != "GET"_method) {
+ boost::string_view csrf = req.get_header_value("X-XSRF-TOKEN");
// Make sure both tokens are filled
if (csrf.empty() || session->csrf_token.empty()) {
return nullptr;
@@ -171,21 +172,21 @@ class Middleware {
// checks if request can be forwarded without authentication
bool is_on_whitelist(const crow::request& req) const {
- // it's allowed to GET root node without authentication
- if ("GET"_method == req.method) {
- CROW_LOG_DEBUG << "TESTING ROUTE " << req.url;
+ // it's allowed to GET root node without authentica tion
+ if ("GET"_method == req.method()) {
if (req.url == "/redfish/v1" || req.url == "/redfish/v1/") {
return true;
- } else if (crow::webassets::routes.find(req.url) !=
+ } else if (crow::webassets::routes.find(std::string(req.url)) !=
crow::webassets::routes.end()) {
return true;
}
}
- // it's allowed to POST on session collection & login without authentication
- if ("POST"_method == req.method) {
- if ((req.url == "/redfish/v1/SessionService/Sessions" ||
- req.url == "/redfish/v1/SessionService/Sessions/") ||
+ // it's allowed to POST on session collection & login without
+ // authentication
+ if ("POST"_method == req.method()) {
+ if ((req.url == "/redfish/v1/SessionService/Sessions") ||
+ (req.url == "/redfish/v1/SessionService/Sessions/") ||
(req.url == "/login") || (req.url == "/logout")) {
return true;
}
@@ -207,35 +208,38 @@ void request_routes(Crow<Middlewares...>& app) {
CROW_ROUTE(app, "/login")
.methods(
"POST"_method)([&](const crow::request& req, crow::response& res) {
- std::string content_type;
- auto content_type_it = req.headers.find("content-type");
- if (content_type_it != req.headers.end()) {
- content_type = content_type_it->second;
- boost::algorithm::to_lower(content_type);
- }
- const std::string* username;
- const std::string* password;
+ boost::string_view content_type = req.get_header_value("content-type");
+ boost::string_view username;
+ boost::string_view password;
+
bool looks_like_ibm = false;
- // This object needs to be declared at this scope so the strings within
- // it are not destroyed before we can use them
+ // 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;
// 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()) {
- res.code = 400;
+ res.result(boost::beast::http::status::bad_request);
res.end();
return;
}
+
// check for username/password in the root object
// THis method is how intel APIs authenticate
- auto user_it = login_credentials.find("username");
- auto pass_it = login_credentials.find("password");
+ 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()) {
- username = user_it->get_ptr<const std::string*>();
- password = pass_it->get_ptr<const std::string*>();
+ 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;
+ }
} else {
// Openbmc appears to push a data object that contains the same
// keys (username and password), attempt to use that
@@ -245,56 +249,70 @@ void request_routes(Crow<Middlewares...>& app) {
// "password"]
if (data_it->is_array()) {
if (data_it->size() == 2) {
- username = (*data_it)[0].get_ptr<const std::string*>();
- password = (*data_it)[1].get_ptr<const std::string*>();
+ 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;
+ }
+ }
}
+
} else if (data_it->is_object()) {
- auto user_it = data_it->find("username");
- auto pass_it = data_it->find("password");
- if (user_it != data_it->end() && pass_it != data_it->end()) {
- username = user_it->get_ptr<const std::string*>();
- password = pass_it->get_ptr<const std::string*>();
+ 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 {
- // check if auth was provided as a query string
- auto user_it = req.headers.find("username");
- auto pass_it = req.headers.find("password");
- if (user_it != req.headers.end() && pass_it != req.headers.end()) {
- username = &user_it->second;
- password = &pass_it->second;
- }
+ // check if auth was provided as a headers
+ username = req.get_header_value("username");
+ password = req.get_header_value("password");
}
- if (username != nullptr && !username->empty() && password != nullptr &&
- !password->empty()) {
- if (!pam_authenticate_user(*username, *password)) {
- res.code = res.code = static_cast<int>(HttpRespCode::UNAUTHORIZED);
+ if (!username.empty() && !password.empty()) {
+ if (!pam_authenticate_user(username, password)) {
+ res.result(boost::beast::http::status::unauthorized);
} else {
- auto& session =
- PersistentData::session_store->generate_user_session(*username);
+ auto session =
+ PersistentData::session_store->generate_user_session(username);
if (looks_like_ibm) {
// IBM requires a very specific login structure, and doesn't
// actually look at the status code. TODO(ed).... Fix that
// upstream
- res.json_value = {{"data", "User '" + *username + "' logged in"},
- {"message", "200 OK"},
- {"status", "ok"}};
- res.add_header("Set-Cookie", "XSRF-TOKEN=" + session.csrf_token);
- res.add_header("Set-Cookie", "SESSION=" + session.session_token +
+ res.json_value = {
+ {"data", "User '" + std::string(username) + "' logged in"},
+ {"message", "200 OK"},
+ {"status", "ok"}};
+ res.add_header("Set-Cookie", "XSRF-TOKEN=" + session->csrf_token);
+ res.add_header("Set-Cookie", "SESSION=" + session->session_token +
"; Secure; HttpOnly");
} else {
// if content type is json, assume json token
- res.json_value = {{"token", session.session_token}};
+ res.json_value = {{"token", session->session_token}};
}
}
} else {
- res.code = static_cast<int>(HttpRespCode::BAD_REQUEST);
+ res.result(boost::beast::http::status::bad_request);
}
res.end();
});
@@ -308,7 +326,6 @@ void request_routes(Crow<Middlewares...>& app) {
if (session != nullptr) {
PersistentData::session_store->remove_session(session);
}
- res.code = static_cast<int>(HttpRespCode::OK);
res.end();
return;
diff --git a/include/webassets.hpp b/include/webassets.hpp
index 6384f3abc3..85de3addf4 100644
--- a/include/webassets.hpp
+++ b/include/webassets.hpp
@@ -4,7 +4,6 @@
#include <fstream>
#include <string>
#include <crow/app.h>
-#include <crow/http_codes.h>
#include <crow/http_request.h>
#include <crow/http_response.h>
#include <crow/routing.h>
@@ -88,7 +87,7 @@ void request_routes(Crow<Middlewares...>& app) {
auto content_type_it = content_types.find(extension.c_str());
if (content_type_it == content_types.end()) {
- CROW_LOG_ERROR << "Cannot determine content-type for " << webpath
+ CROW_LOG_ERROR << "Cannot determine content-type for " << absolute_path
<< " with extension " << extension;
} else {
content_type = content_type_it->second;
@@ -109,13 +108,12 @@ void request_routes(Crow<Middlewares...>& app) {
std::ifstream inf(absolute_path);
if (!inf) {
CROW_LOG_DEBUG << "failed to read file";
- res.code = static_cast<int>(HttpRespCode::NOT_FOUND);
- res.code = static_cast<int>(HttpRespCode::INTERNAL_ERROR);
+ res.result(boost::beast::http::status::internal_server_error);
res.end();
return;
}
- res.body = {std::istreambuf_iterator<char>(inf),
+ res.body() = {std::istreambuf_iterator<char>(inf),
std::istreambuf_iterator<char>()};
res.end();
});