diff --git a/sunshine/confighttp.cpp b/sunshine/confighttp.cpp index e76b8ca4..6546b31d 100644 --- a/sunshine/confighttp.cpp +++ b/sunshine/confighttp.cpp @@ -76,14 +76,14 @@ bool authenticate(resp_https_t response, req_https_t request) { int index = authData.find(':'); std::string username = authData.substr(0, index); std::string password = authData.substr(index + 1); - std::string hash = crypto::hash_hexstr(password + config::sunshine.salt); + std::string hash = util::hex(crypto::hash(password + config::sunshine.salt)).to_string(); if(username == config::sunshine.username && hash == config::sunshine.password) return true; + send_unauthorized(response, request); return false; } -template -void not_found(std::shared_ptr::Response> response, std::shared_ptr::Request> request) { +void not_found(resp_https_t response, req_https_t request) { pt::ptree tree; tree.put("root..status_code", 404); @@ -98,46 +98,47 @@ void not_found(std::shared_ptr::Response> resp void getIndexPage(resp_https_t response, req_https_t request) { if(!authenticate(response, request)) return; + std::string header = read_file(WEB_DIR "header.html"); std::string content = read_file(WEB_DIR "index.html"); response->write(header + content); } -template -void getPinPage(std::shared_ptr::Response> response, std::shared_ptr::Request> request) { +void getPinPage(resp_https_t response, req_https_t request) { if(!authenticate(response, request)) return; + std::string header = read_file(WEB_DIR "header.html"); std::string content = read_file(WEB_DIR "pin.html"); response->write(header + content); } -template -void getAppsPage(std::shared_ptr::Response> response, std::shared_ptr::Request> request) { +void getAppsPage(resp_https_t response, req_https_t request) { if(!authenticate(response, request)) return; + std::string header = read_file(WEB_DIR "header.html"); std::string content = read_file(WEB_DIR "apps.html"); response->write(header + content); } -template -void getClientsPage(std::shared_ptr::Response> response, std::shared_ptr::Request> request) { +void getClientsPage(resp_https_t response, req_https_t request) { if(!authenticate(response, request)) return; + std::string header = read_file(WEB_DIR "header.html"); std::string content = read_file(WEB_DIR "clients.html"); response->write(header + content); } -template -void getConfigPage(std::shared_ptr::Response> response, std::shared_ptr::Request> request) { +void getConfigPage(resp_https_t response, req_https_t request) { if(!authenticate(response, request)) return; + std::string header = read_file(WEB_DIR "header.html"); std::string content = read_file(WEB_DIR "config.html"); response->write(header + content); } -template -void getPasswordPage(std::shared_ptr::Response> response, std::shared_ptr::Request> request) { +void getPasswordPage(resp_https_t response, req_https_t request) { if(!authenticate(response, request)) return; + std::string header = read_file(WEB_DIR "header.html"); std::string content = read_file(WEB_DIR "password.html"); response->write(header + content); @@ -145,12 +146,14 @@ void getPasswordPage(std::shared_ptr::Response void getApps(resp_https_t response, req_https_t request) { if(!authenticate(response, request)) return; + std::string content = read_file(SUNSHINE_ASSETS_DIR "/" APPS_JSON); response->write(content); } void saveApp(resp_https_t response, req_https_t request) { if(!authenticate(response, request)) return; + std::stringstream ss; ss << request->content.rdbuf(); pt::ptree outputTree; @@ -170,12 +173,13 @@ void saveApp(resp_https_t response, req_https_t request) { BOOST_LOG(info) << inputTree.get_child("prep-cmd").empty(); if(inputTree.get_child("prep-cmd").empty()) inputTree.erase("prep-cmd"); + inputTree.erase("index"); if(index == -1) { apps_node.push_back(std::make_pair("", inputTree)); } else { - //Unfortuantely Boost PT does not allow to directly edit the array, copt should do the trick + //Unfortuantely Boost PT does not allow to directly edit the array, copy should do the trick pt::ptree newApps; int i = 0; for(const auto &kv : apps_node) { @@ -204,6 +208,7 @@ void saveApp(resp_https_t response, req_https_t request) { void deleteApp(resp_https_t response, req_https_t request) { if(!authenticate(response, request)) return; + pt::ptree outputTree; auto g = util::fail_guard([&]() { std::ostringstream data; @@ -249,6 +254,7 @@ void deleteApp(resp_https_t response, req_https_t request) { void getConfig(resp_https_t response, req_https_t request) { if(!authenticate(response, request)) return; + pt::ptree outputTree; auto g = util::fail_guard([&]() { std::ostringstream data; @@ -285,6 +291,7 @@ void getConfig(resp_https_t response, req_https_t request) { void saveConfig(resp_https_t response, req_https_t request) { if(!authenticate(response, request)) return; + std::stringstream ss; std::stringstream configStream; ss << request->content.rdbuf(); @@ -302,6 +309,7 @@ void saveConfig(resp_https_t response, req_https_t request) { for(const auto &kv : inputTree) { std::string value = inputTree.get(kv.first); if(value.length() == 0 || value.compare("null") == 0) continue; + configStream << kv.first << " = " << value << std::endl; } http::write_file(SUNSHINE_ASSETS_DIR "/sunshine.conf", configStream.str()); @@ -316,6 +324,7 @@ void saveConfig(resp_https_t response, req_https_t request) { void savePassword(resp_https_t response, req_https_t request) { if(!authenticate(response, request)) return; + std::stringstream ss; std::stringstream configStream; ss << request->content.rdbuf(); @@ -337,14 +346,15 @@ void savePassword(resp_https_t response, req_https_t request) { std::string newPassword = inputTree.get("newPassword"); std::string confirmPassword = inputTree.get("confirmNewPassword"); if(newUsername.length() == 0) newUsername = username; - std::string hash = crypto::hash_hexstr(password + config::sunshine.salt); + + std::string hash = util::hex(crypto::hash(password + config::sunshine.salt)).to_string(); if(username == config::sunshine.username && hash == config::sunshine.password){ if(newPassword != confirmPassword){ outputTree.put("status",false); outputTree.put("error","Password Mismatch"); } fileTree.put("username",newUsername); - fileTree.put("password",crypto::hash_hexstr(newPassword + config::sunshine.salt)); + fileTree.put("password",util::hex(crypto::hash(newPassword + config::sunshine.salt)).to_string()); fileTree.put("salt",config::sunshine.salt); pt::write_json(config::sunshine.credentials_file,fileTree); http::reload_user_creds(config::sunshine.credentials_file); @@ -366,27 +376,27 @@ void start(std::shared_ptr shutdown_event) { auto ctx = std::make_shared(boost::asio::ssl::context::tls); ctx->use_certificate_chain_file(config::nvhttp.cert); ctx->use_private_key_file(config::nvhttp.pkey, boost::asio::ssl::context::pem); - https_server_t http_server { ctx, 0 }; - http_server.default_resource = not_found; - http_server.resource["^/$"]["GET"] = getIndexPage; - http_server.resource["^/pin$"]["GET"] = getPinPage; - http_server.resource["^/apps$"]["GET"] = getAppsPage; - http_server.resource["^/clients$"]["GET"] = getClientsPage; - http_server.resource["^/config$"]["GET"] = getConfigPage; - http_server.resource["^/password$"]["GET"] = getPasswordPage; - http_server.resource["^/pin/([0-9]+)$"]["GET"] = nvhttp::pin; - http_server.resource["^/api/apps$"]["GET"] = getApps; - http_server.resource["^/api/apps$"]["POST"] = saveApp; - http_server.resource["^/api/config$"]["GET"] = getConfig; - http_server.resource["^/api/config$"]["POST"] = saveConfig; - http_server.resource["^/api/password$"]["POST"] = savePassword; - http_server.resource["^/api/apps/([0-9]+)$"]["DELETE"] = deleteApp; - http_server.config.reuse_address = true; - http_server.config.address = "0.0.0.0"s; - http_server.config.port = PORT_HTTP; + https_server_t server { ctx, 0 }; + server.default_resource = not_found; + server.resource["^/$"]["GET"] = getIndexPage; + server.resource["^/pin$"]["GET"] = getPinPage; + server.resource["^/apps$"]["GET"] = getAppsPage; + server.resource["^/clients$"]["GET"] = getClientsPage; + server.resource["^/config$"]["GET"] = getConfigPage; + server.resource["^/password$"]["GET"] = getPasswordPage; + server.resource["^/pin/([0-9]+)$"]["GET"] = nvhttp::pin; + server.resource["^/api/apps$"]["GET"] = getApps; + server.resource["^/api/apps$"]["POST"] = saveApp; + server.resource["^/api/config$"]["GET"] = getConfig; + server.resource["^/api/config$"]["POST"] = saveConfig; + server.resource["^/api/password$"]["POST"] = savePassword; + server.resource["^/api/apps/([0-9]+)$"]["DELETE"] = deleteApp; + server.config.reuse_address = true; + server.config.address = "0.0.0.0"s; + server.config.port = PORT_HTTP; try { - http_server.bind(); + server.bind(); BOOST_LOG(info) << "Configuration UI available at [https://localhost:"sv << PORT_HTTP << "]"; } catch(boost::system::system_error &err) { @@ -395,12 +405,12 @@ void start(std::shared_ptr shutdown_event) { shutdown_event->raise(true); return; } - auto accept_and_run = [&](auto *http_server) { + auto accept_and_run = [&](auto *server) { try { - http_server->accept_and_run(); + server->accept_and_run(); } catch(boost::system::system_error &err) { - // It's possible the exception gets thrown after calling http_server->stop() from a different thread + // It's possible the exception gets thrown after calling server->stop() from a different thread if(shutdown_event->peek()) { return; } @@ -410,12 +420,12 @@ void start(std::shared_ptr shutdown_event) { return; } }; - std::thread tcp { accept_and_run, &http_server }; + std::thread tcp { accept_and_run, &server }; // Wait for any event shutdown_event->view(); - http_server.stop(); + server.stop(); tcp.join(); } diff --git a/sunshine/httpcommon.cpp b/sunshine/httpcommon.cpp index b6f7ac0a..825ae3d6 100644 --- a/sunshine/httpcommon.cpp +++ b/sunshine/httpcommon.cpp @@ -72,7 +72,7 @@ int generate_user_creds(const std::string &file) { std::string salt = crypto::rand_string(16); outputTree.put("username", "sunshine"); outputTree.put("salt", salt); - outputTree.put("password", crypto::hash_hexstr(plainPassword + salt)); + outputTree.put("password", util::hex(crypto::hash(plainPassword + salt)).to_string()); BOOST_LOG(info) << "New credentials has been created"; BOOST_LOG(info) << "Username: " << username; BOOST_LOG(info) << "Password: " << plainPassword;