diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/ast_video_puller_test.cpp | 2 | ||||
-rw-r--r-- | src/getvideo_main.cpp | 2 | ||||
-rw-r--r-- | src/security_headers_middleware.cpp | 39 | ||||
-rw-r--r-- | src/token_authorization_middleware.cpp | 192 | ||||
-rw-r--r-- | src/token_authorization_middleware_test.cpp | 13 | ||||
-rw-r--r-- | src/webserver_main.cpp | 91 |
6 files changed, 54 insertions, 285 deletions
diff --git a/src/ast_video_puller_test.cpp b/src/ast_video_puller_test.cpp index ef1cbe3b6d..b1f94e7579 100644 --- a/src/ast_video_puller_test.cpp +++ b/src/ast_video_puller_test.cpp @@ -14,7 +14,6 @@ #include <gtest/gtest.h> TEST(AstvideoPuller, BasicRead) { - std::cout << "Started\n"; AstVideo::RawVideoBuffer out; bool have_hardware = false; if (access("/dev/video", F_OK) != -1) { @@ -43,7 +42,6 @@ TEST(AstvideoPuller, BasicRead) { fwrite(out.buffer.data(), sizeof(char), out.buffer.size(), fp); AstVideo::AstJpegDecoder d; - std::cout << "MODE " << static_cast<int>(out.mode); d.decode(out.buffer, out.width, out.height, out.mode, out.y_selector, out.uv_selector); } diff --git a/src/getvideo_main.cpp b/src/getvideo_main.cpp index 33885ee117..2ab0c0e0c9 100644 --- a/src/getvideo_main.cpp +++ b/src/getvideo_main.cpp @@ -20,7 +20,6 @@ #include <ast_video_puller.hpp> int main() { - std::cout << "Started\n"; AstVideo::RawVideoBuffer out; bool have_hardware = false; if (access("/dev/video", F_OK) != -1) { @@ -49,7 +48,6 @@ int main() { fwrite(out.buffer.data(), sizeof(char), out.buffer.size(), fp); AstVideo::AstJpegDecoder d; - std::cout << "MODE " << static_cast<int>(out.mode); d.decode(out.buffer, out.width, out.height, out.mode, out.y_selector, out.uv_selector); #ifdef BUILD_CIMG diff --git a/src/security_headers_middleware.cpp b/src/security_headers_middleware.cpp deleted file mode 100644 index 265cda72a7..0000000000 --- a/src/security_headers_middleware.cpp +++ /dev/null @@ -1,39 +0,0 @@ -#include <security_headers_middleware.hpp> - -namespace crow { - -static const std::string strict_transport_security_key = - "Strict-Transport-Security"; -static const std::string strict_transport_security_value = - "max-age=31536000; includeSubdomains; preload"; - -static const std::string ua_compatability_key = "X-UA-Compatible"; -static const std::string ua_compatability_value = "IE=11"; - -static const std::string xframe_key = "X-Frame-Options"; -static const std::string xframe_value = "DENY"; - -static const std::string xss_key = "X-XSS-Protection"; -static const std::string xss_value = "1; mode=block"; - -static const std::string content_security_key = "X-Content-Security-Policy"; -static const std::string content_security_value = "default-src 'self'"; - -void SecurityHeadersMiddleware::before_handle(crow::request& req, response& res, - context& ctx) {} - -void SecurityHeadersMiddleware::after_handle(request& /*req*/, response& res, - context& ctx) { - /* - TODO(ed) these should really check content types. for example, - X-UA-Compatible header doesn't make sense when retrieving a JSON or - javascript file. It doesn't hurt anything, it's just ugly. - */ - res.add_header(strict_transport_security_key, - strict_transport_security_value); - res.add_header(ua_compatability_key, ua_compatability_value); - res.add_header(xframe_key, xframe_value); - res.add_header(xss_key, xss_value); - res.add_header(content_security_key, content_security_value); -} -} diff --git a/src/token_authorization_middleware.cpp b/src/token_authorization_middleware.cpp deleted file mode 100644 index 508bfd982c..0000000000 --- a/src/token_authorization_middleware.cpp +++ /dev/null @@ -1,192 +0,0 @@ -#include <random> -#include <unordered_map> -#include <boost/algorithm/string/predicate.hpp> - -#include <security/pam_appl.h> -#include <base64.hpp> -#include <token_authorization_middleware.hpp> -#include <crow/logging.h> - -namespace crow { - -using random_bytes_engine = - std::independent_bits_engine<std::default_random_engine, CHAR_BIT, - unsigned char>; - -// function used to get user input -int pam_function_conversation(int num_msg, const struct pam_message** msg, - struct pam_response** resp, void* appdata_ptr) { - char* pass = (char*)malloc(strlen((char*)appdata_ptr) + 1); - strcpy(pass, (char*)appdata_ptr); - - int i; - - *resp = (pam_response*)calloc(num_msg, sizeof(struct pam_response)); - - for (i = 0; i < num_msg; ++i) { - /* Ignore all PAM messages except prompting for hidden input */ - if (msg[i]->msg_style != PAM_PROMPT_ECHO_OFF) continue; - - /* Assume PAM is only prompting for the password as hidden input */ - resp[i]->resp = pass; - } - - return PAM_SUCCESS; -} - -bool authenticate_user_pam(const std::string& username, - const std::string& password) { - const struct pam_conv local_conversation = {pam_function_conversation, - (char*)password.c_str()}; - pam_handle_t* local_auth_handle = NULL; // this gets set by pam_start - - int retval; - retval = pam_start("su", username.c_str(), &local_conversation, - &local_auth_handle); - - if (retval != PAM_SUCCESS) { - printf("pam_start returned: %d\n ", retval); - return false; - } - - retval = pam_authenticate(local_auth_handle, - PAM_SILENT | PAM_DISALLOW_NULL_AUTHTOK); - - if (retval != PAM_SUCCESS) { - if (retval == PAM_AUTH_ERR) { - printf("Authentication failure.\n"); - } else { - printf("pam_authenticate returned %d\n", retval); - } - return false; - } - - printf("Authenticated.\n"); - retval = pam_end(local_auth_handle, retval); - - if (retval != PAM_SUCCESS) { - printf("pam_end returned\n"); - return false; - } - - return true; -} - -TokenAuthorizationMiddleware::TokenAuthorizationMiddleware(){ -}; - -void TokenAuthorizationMiddleware::before_handle(crow::request& req, - response& res, context& ctx) { - auto return_unauthorized = [&req, &res]() { - res.code = 401; - res.end(); - }; - - auto return_bad_request = [&req, &res]() { - res.code = 400; - res.end(); - }; - - auto return_internal_error = [&req, &res]() { - res.code = 500; - res.end(); - }; - - if (req.url == "/" || boost::starts_with(req.url, "/static/")) { - // TODO this is total hackery to allow the login page to work before the - // user is authenticated. Also, it will be quite slow for all pages instead - // of a one time hit for the whitelist entries. Ideally, this should be - // done in the url router handler, with tagged routes for the whitelist - // entries. Another option would be to whitelist a minimal for based page - // that didn't - // load the full angular UI until after login - return; - } - - if (req.url == "/login") { - if (req.method != HTTPMethod::POST) { - return_unauthorized(); - return; - } else { - auto login_credentials = crow::json::load(req.body); - if (!login_credentials) { - return_bad_request(); - return; - } - if (!login_credentials.has("username") || - !login_credentials.has("password")) { - return_bad_request(); - return; - } - auto username = login_credentials["username"].s(); - auto password = login_credentials["password"].s(); - - // TODO(ed) pull real passwords from PAM - if (authenticate_user_pam(username, password)) { - crow::json::wvalue x; - - // TODO(ed) the RNG should be initialized at start, not every time we - // want a token - std::random_device rand; - random_bytes_engine rbe; - std::string token('a', 20); - // TODO(ed) for some reason clang-tidy finds a divide by zero error in - // cstdlibc here commented out for now. Needs investigation - std::generate(begin(token), end(token), std::ref(rbe)); // NOLINT - std::string encoded_token; - base64::base64_encode(token, encoded_token); - // ctx.auth_token = encoded_token; - this->auth_token2.insert(encoded_token); - - x["token"] = encoded_token; - - res.write(json::dump(x)); - res.add_header("Content-Type", "application/json"); - res.end(); - } else { - return_unauthorized(); - return; - } - } - - } else { // Normal, non login, non static file request - // Check to make sure we're logged in - if (this->auth_token2.empty()) { - return_unauthorized(); - return; - } - // Check for an authorization header, reject if not present - if (req.headers.count("Authorization") != 1) { - return_unauthorized(); - return; - } - - std::string auth_header = req.get_header_value("Authorization"); - // If the user is attempting any kind of auth other than token, reject - if (!boost::starts_with(auth_header, "Token ")) { - return_unauthorized(); - return; - } - std::string auth_key = auth_header.substr(6); - // TODO(ed), use span here instead of constructing a new string - if (this->auth_token2.find(auth_key) == this->auth_token2.end()) { - return_unauthorized(); - return; - } - - if (req.url == "/logout") { - this->auth_token2.erase(auth_key); - res.code = 200; - res.end(); - return; - } - - // else let the request continue unharmed - } -} - -void TokenAuthorizationMiddleware::after_handle(request& req, response& res, - context& ctx) { - // Do nothing -} -} diff --git a/src/token_authorization_middleware_test.cpp b/src/token_authorization_middleware_test.cpp index e82776533e..49933c9954 100644 --- a/src/token_authorization_middleware_test.cpp +++ b/src/token_authorization_middleware_test.cpp @@ -6,6 +6,14 @@ using namespace crow; using namespace std; +class KnownLoginAuthenticator { + public: + inline bool authenticate(const std::string& username, + const std::string& password) { + return (username == "dude") && (password == "foo"); + } +}; + // Tests that static urls are correctly passed TEST(TokenAuthentication, TestBasicReject) { App<crow::TokenAuthorizationMiddleware> app; @@ -177,9 +185,8 @@ TEST(TokenAuthentication, TestPostBadLoginUrl) { app.stop(); } -// Tests boundary conditions on login TEST(TokenAuthentication, TestSuccessfulLogin) { - App<crow::TokenAuthorizationMiddleware> app; + App<crow::TokenAuthorization<KnownLoginAuthenticator>> app; app.bindaddr("127.0.0.1").port(45451); CROW_ROUTE(app, "/")([]() { return 200; }); auto _ = async(launch::async, [&] { app.run(); }); @@ -215,7 +222,7 @@ TEST(TokenAuthentication, TestSuccessfulLogin) { // Test correct login credentials sendmsg = "POST /login\r\nContent-Length:40\r\n\r\n{\"username\": \"dude\", " - "\"password\": \"dude\"}\r\n"; + "\"password\": \"foo\"}\r\n"; { send_to_localhost(sendmsg); std::string response(std::begin(buf), std::end(buf)); diff --git a/src/webserver_main.cpp b/src/webserver_main.cpp index 0c173dd947..3baf388a24 100644 --- a/src/webserver_main.cpp +++ b/src/webserver_main.cpp @@ -246,9 +246,20 @@ int main(int argc, char** argv) { return j; }); - CROW_ROUTE(app, "/ipmiws") + CROW_ROUTE(app, "/sensorws") .websocket() .onopen([&](crow::websocket::connection& conn) { + dbus::connection system_bus(conn.get_io_service(), dbus::bus::system); + dbus::match ma(system_bus, + "type='signal',sender='org.freedesktop.DBus', " + "interface='org.freedesktop.DBus.Properties',member=" + "'PropertiesChanged'"); + dbus::filter f(system_bus, [](dbus::message& m) { return true; }); + + f.async_dispatch([&](boost::system::error_code ec, dbus::message s) { + std::cout << "got event\n"; + //f.async_dispatch(event_handler); + }); }) .onclose( @@ -257,57 +268,43 @@ int main(int argc, char** argv) { }) .onmessage([&](crow::websocket::connection& conn, const std::string& data, bool is_binary) { - boost::asio::io_service io_service; - using boost::asio::ip::udp; - udp::resolver resolver(io_service); - udp::resolver::query query(udp::v4(), "10.243.48.31", "623"); - udp::endpoint receiver_endpoint = *resolver.resolve(query); - - udp::socket socket(io_service); - socket.open(udp::v4()); - - socket.send_to(boost::asio::buffer(data), receiver_endpoint); - - std::array<char, 255> recv_buf; - - udp::endpoint sender_endpoint; - size_t len = - socket.receive_from(boost::asio::buffer(recv_buf), sender_endpoint); - // TODO(ed) THis is ugly. Find a way to not make a copy (ie, use - // std::string::data() to - std::string str(std::begin(recv_buf), std::end(recv_buf)); - LOG(DEBUG) << "Got " << str << "back \n"; - conn.send_binary(str); }); CROW_ROUTE(app, "/sensortest") ([](const crow::request& req, crow::response& res) { - dbus::connection system_bus(*req.io_service, dbus::bus::system); - - dbus::endpoint test_daemon("org.freedesktop.DBus", "/", - "org.freedesktop.DBus"); - dbus::message m = dbus::message::new_call(test_daemon, "ListNames"); - system_bus.async_send(m, [&](const boost::system::error_code ec, - dbus::message r) { - std::vector<std::string> services; - //r.unpack(services); - for (auto& service : services) { - dbus::endpoint service_daemon(service, "/", - "org.freedesktop.DBus.Introspectable"); - dbus::message m = dbus::message::new_call(service_daemon, "Introspect"); - system_bus.async_send( - m, [&](const boost::system::error_code ec, dbus::message r) { - std::string xml; - r.unpack(xml); - std::vector<std::string> dbus_objects; - dbus::read_dbus_xml_names(xml, dbus_objects); - - - }); - } + crow::json::wvalue j; + auto values = read_sensor_values(); - }); + dbus::connection system_bus(*req.io_service, dbus::bus::system); + dbus::endpoint test_daemon("org.openbmc.Sensors", + "/org/openbmc/sensors/tach", + "org.freedesktop.DBus.Introspectable"); + dbus::message m = dbus::message::new_call(test_daemon, "Introspect"); + system_bus.async_send( + m, + [&j, &system_bus](const boost::system::error_code ec, dbus::message r) { + std::string xml; + r.unpack(xml); + std::vector<std::string> dbus_objects; + dbus::read_dbus_xml_names(xml, dbus_objects); + + for (auto& object : dbus_objects) { + dbus::endpoint test_daemon("org.openbmc.Sensors", + "/org/openbmc/sensors/tach/" + object, + "org.openbmc.SensorValue"); + dbus::message m2 = dbus::message::new_call(test_daemon, "getValue"); + + system_bus.async_send( + m2, [&](const boost::system::error_code ec, dbus::message r) { + int32_t value; + r.unpack(value); + // TODO(ed) if we ever go multithread, j needs a lock + j[object] = value; + }); + } + + }); }); @@ -337,6 +334,6 @@ int main(int argc, char** argv) { auto ssl_context = ensuressl::get_ssl_context(ssl_pem_file); app.ssl(std::move(ssl_context)); } - app.concurrency(4); + //app.concurrency(4); app.run(); } |