diff --git a/sunshine/config.cpp b/sunshine/config.cpp index a990ccf6..f2cf391e 100644 --- a/sunshine/config.cpp +++ b/sunshine/config.cpp @@ -209,12 +209,12 @@ input_t input { }; sunshine_t sunshine { - 2, // min_log_level - 0, // flags - "user_credentials.json"s,//User file - ""s,//Username - ""s,//Password - ""s//Password Salt + 2, // min_log_level + 0, // flags + "user_credentials.json"s, //User file + ""s, //Username + ""s, //Password + ""s //Password Salt }; bool endline(char ch) { diff --git a/sunshine/config.h b/sunshine/config.h index 55b9296d..99f50408 100644 --- a/sunshine/config.h +++ b/sunshine/config.h @@ -4,8 +4,8 @@ #include #include #include -#include #include +#include #include namespace config { @@ -105,5 +105,5 @@ extern sunshine_t sunshine; int parse(int argc, char *argv[]); std::unordered_map parse_config(std::string_view file_content); -} +} // namespace config #endif diff --git a/sunshine/confighttp.cpp b/sunshine/confighttp.cpp index a707d8de..fb20a8dd 100644 --- a/sunshine/confighttp.cpp +++ b/sunshine/confighttp.cpp @@ -6,32 +6,31 @@ #include +#include #include #include -#include #include -#include #include +#include #include #include "config.h" -#include "utility.h" -#include "rtsp.h" -#include "crypto.h" #include "confighttp.h" -#include "platform/common.h" +#include "crypto.h" #include "httpcommon.h" +#include "main.h" #include "network.h" #include "nvhttp.h" +#include "platform/common.h" +#include "rtsp.h" +#include "utility.h" #include "uuid.h" -#include "main.h" std::string read_file(std::string path); -namespace confighttp -{ +namespace confighttp { using namespace std::literals; constexpr auto PORT_HTTP = 47990; @@ -40,28 +39,25 @@ namespace pt = boost::property_tree; using https_server_t = SimpleWeb::Server; -using args_t = SimpleWeb::CaseInsensitiveMultimap; +using args_t = SimpleWeb::CaseInsensitiveMultimap; using resp_https_t = std::shared_ptr::Response>; -using req_https_t = std::shared_ptr::Request>; +using req_https_t = std::shared_ptr::Request>; -enum class op_e -{ +enum class op_e { ADD, REMOVE }; -void send_unauthorized(resp_https_t response, req_https_t request) -{ +void send_unauthorized(resp_https_t response, req_https_t request) { auto address = request->remote_endpoint_address(); BOOST_LOG(info) << '[' << address << "] -- denied"sv; const SimpleWeb::CaseInsensitiveMultimap headers { - {"WWW-Authenticate",R"(Basic realm="Sunshine Gamestream Host", charset="UTF-8")"} + { "WWW-Authenticate", R"(Basic realm="Sunshine Gamestream Host", charset="UTF-8")" } }; - response->write(SimpleWeb::StatusCode::client_error_unauthorized,headers); + response->write(SimpleWeb::StatusCode::client_error_unauthorized, headers); } -bool authenticate(resp_https_t response, req_https_t request) -{ +bool authenticate(resp_https_t response, req_https_t request) { auto address = request->remote_endpoint_address(); auto ip_type = net::from_address(address); if(ip_type > http::origin_pin_allowed) { @@ -70,25 +66,24 @@ bool authenticate(resp_https_t response, req_https_t request) return false; } auto auth = request->header.find("authorization"); - if(auth == request->header.end() ){ - send_unauthorized(response,request); + if(auth == request->header.end()) { + send_unauthorized(response, request); return false; } - std::string rawAuth = auth->second; + std::string rawAuth = auth->second; std::string authData = rawAuth.substr("Basic "sv.length()); - authData = SimpleWeb::Crypto::Base64::decode(authData); - int index = authData.find(':'); - std::string username = authData.substr(0,index); + authData = SimpleWeb::Crypto::Base64::decode(authData); + 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 = crypto::hash_hexstr(password + config::sunshine.salt); if(username == config::sunshine.username && hash == config::sunshine.password) return true; - send_unauthorized(response,request); + send_unauthorized(response, request); return false; } -template -void not_found(std::shared_ptr::Response> response, std::shared_ptr::Request> request) -{ +template +void not_found(std::shared_ptr::Response> response, std::shared_ptr::Request> request) { pt::ptree tree; tree.put("root..status_code", 404); @@ -101,60 +96,53 @@ void not_found(std::shared_ptr::Response> resp << data.str(); } -void getIndexPage(resp_https_t response, req_https_t request) -{ - if(!authenticate(response,request))return; - std::string header = read_file(WEB_DIR "header.html"); +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) -{ - if(!authenticate(response,request))return; - std::string header = read_file(WEB_DIR "header.html"); +template +void getPinPage(std::shared_ptr::Response> response, std::shared_ptr::Request> 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) -{ - if(!authenticate(response,request))return; - std::string header = read_file(WEB_DIR "header.html"); +template +void getAppsPage(std::shared_ptr::Response> response, std::shared_ptr::Request> 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) -{ - if(!authenticate(response,request))return; - std::string header = read_file(WEB_DIR "header.html"); +template +void getClientsPage(std::shared_ptr::Response> response, std::shared_ptr::Request> 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) -{ - if(!authenticate(response,request))return; - std::string header = read_file(WEB_DIR "header.html"); +template +void getConfigPage(std::shared_ptr::Response> response, std::shared_ptr::Request> 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); } -void getApps(resp_https_t response, req_https_t request) -{ - if(!authenticate(response,request))return; +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; +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; @@ -165,34 +153,28 @@ void saveApp(resp_https_t response, req_https_t request) response->write(data.str()); }); pt::ptree inputTree, fileTree; - try - { + try { //TODO: Input Validation pt::read_json(ss, inputTree); pt::read_json(SUNSHINE_ASSETS_DIR "/" APPS_JSON, fileTree); auto &apps_node = fileTree.get_child("apps"s); - int index = inputTree.get("index"); + int index = inputTree.get("index"); BOOST_LOG(info) << inputTree.get_child("prep-cmd").empty(); - if (inputTree.get_child("prep-cmd").empty()) + if(inputTree.get_child("prep-cmd").empty()) inputTree.erase("prep-cmd"); inputTree.erase("index"); - if (index == -1) - { + if(index == -1) { apps_node.push_back(std::make_pair("", inputTree)); } - else - { + else { //Unfortuantely Boost PT does not allow to directly edit the array, copt should do the trick pt::ptree newApps; int i = 0; - for (const auto &kv : apps_node) - { - if (i == index) - { + for(const auto &kv : apps_node) { + if(i == index) { newApps.push_back(std::make_pair("", inputTree)); } - else - { + else { newApps.push_back(std::make_pair("", kv.second)); } i++; @@ -204,8 +186,7 @@ void saveApp(resp_https_t response, req_https_t request) outputTree.put("status", "true"); proc::refresh(SUNSHINE_ASSETS_DIR "/" APPS_JSON); } - catch (std::exception &e) - { + catch(std::exception &e) { BOOST_LOG(warning) << e.what(); outputTree.put("status", "false"); outputTree.put("error", "Invalid Input JSON"); @@ -213,9 +194,8 @@ 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; +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; @@ -224,27 +204,22 @@ void deleteApp(resp_https_t response, req_https_t request) response->write(data.str()); }); pt::ptree fileTree; - try - { + try { pt::read_json(config::stream.file_apps, fileTree); auto &apps_node = fileTree.get_child("apps"s); - int index = stoi(request->path_match[1]); + int index = stoi(request->path_match[1]); BOOST_LOG(info) << index; - if (index <= 0) - { + if(index <= 0) { outputTree.put("status", "false"); outputTree.put("error", "Invalid Index"); return; } - else - { + else { //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) - { - if (i != index) - { + for(const auto &kv : apps_node) { + if(i != index) { newApps.push_back(std::make_pair("", kv.second)); } i++; @@ -256,8 +231,7 @@ void deleteApp(resp_https_t response, req_https_t request) outputTree.put("status", "true"); proc::refresh(SUNSHINE_ASSETS_DIR "/" APPS_JSON); } - catch (std::exception &e) - { + catch(std::exception &e) { BOOST_LOG(warning) << e.what(); outputTree.put("status", "false"); outputTree.put("error", "Invalid File JSON"); @@ -265,9 +239,8 @@ 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; +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; @@ -275,10 +248,9 @@ void getConfig(resp_https_t response, req_https_t request) pt::write_json(data, outputTree); response->write(data.str()); }); - try - { - outputTree.put("status","true"); - outputTree.put("platform",SUNSHINE_PLATFORM); + try { + outputTree.put("status", "true"); + outputTree.put("platform", SUNSHINE_PLATFORM); const char *config_file = SUNSHINE_ASSETS_DIR "/sunshine.conf"; std::ifstream in { config_file }; @@ -289,15 +261,13 @@ void getConfig(resp_https_t response, req_https_t request) auto vars = config::parse_config(std::string { // Quick and dirty std::istreambuf_iterator(in), - std::istreambuf_iterator() - }); + std::istreambuf_iterator() }); - for(auto &[name,value] : vars) { + for(auto &[name, value] : vars) { outputTree.put(std::move(name), std::move(value)); } } - catch (std::exception &e) - { + catch(std::exception &e) { BOOST_LOG(warning) << e.what(); outputTree.put("status", "false"); outputTree.put("error", "Invalid File JSON"); @@ -305,9 +275,8 @@ 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; +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(); @@ -319,20 +288,17 @@ void saveConfig(resp_https_t response, req_https_t request) response->write(data.str()); }); pt::ptree inputTree; - try - { + try { //TODO: Input Validation pt::read_json(ss, inputTree); - for (const auto &kv : inputTree) - { + for(const auto &kv : inputTree) { std::string value = inputTree.get(kv.first); - if(value.length() == 0 || value.compare("null") == 0)continue; + 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()); + http::write_file(SUNSHINE_ASSETS_DIR "/sunshine.conf", configStream.str()); } - catch (std::exception &e) - { + catch(std::exception &e) { BOOST_LOG(warning) << e.what(); outputTree.put("status", "false"); outputTree.put("error", e.what()); @@ -340,50 +306,44 @@ void saveConfig(resp_https_t response, req_https_t request) } } -void start(std::shared_ptr shutdown_event) -{ +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["^/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; + 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["^/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/apps/([0-9]+)$"]["DELETE"] = deleteApp; - http_server.resource["^/clients$"]["GET"] = getClientsPage; - http_server.resource["^/config$"]["GET"] = getConfigPage; - http_server.resource["^/pin/([0-9]+)$"]["GET"] = nvhttp::pin; - http_server.config.reuse_address = true; - http_server.config.address = "0.0.0.0"s; - http_server.config.port = PORT_HTTP; + http_server.resource["^/clients$"]["GET"] = getClientsPage; + http_server.resource["^/config$"]["GET"] = getConfigPage; + http_server.resource["^/pin/([0-9]+)$"]["GET"] = nvhttp::pin; + http_server.config.reuse_address = true; + http_server.config.address = "0.0.0.0"s; + http_server.config.port = PORT_HTTP; - try - { + try { http_server.bind(); BOOST_LOG(info) << "Configuration UI available at [https://localhost:"sv << PORT_HTTP << "]"; } - catch (boost::system::system_error &err) - { + catch(boost::system::system_error &err) { BOOST_LOG(fatal) << "Couldn't bind http server to ports ["sv << PORT_HTTP << "]: "sv << err.what(); shutdown_event->raise(true); return; } auto accept_and_run = [&](auto *http_server) { - try - { + try { http_server->accept_and_run(); } - catch (boost::system::system_error &err) - { + catch(boost::system::system_error &err) { // It's possible the exception gets thrown after calling http_server->stop() from a different thread - if (shutdown_event->peek()) - { + if(shutdown_event->peek()) { return; } @@ -392,7 +352,7 @@ void start(std::shared_ptr shutdown_event) return; } }; - std::thread tcp{accept_and_run, &http_server}; + std::thread tcp { accept_and_run, &http_server }; // Wait for any event shutdown_event->view(); @@ -401,18 +361,16 @@ void start(std::shared_ptr shutdown_event) tcp.join(); } -} +} // namespace confighttp -std::string read_file(std::string path) -{ +std::string read_file(std::string path) { std::ifstream in(path); std::string input; std::string base64_cert; //FIXME: Being unable to read file could result in infinite loop - while (!in.eof()) - { + while(!in.eof()) { std::getline(in, input); base64_cert += input + '\n'; } diff --git a/sunshine/confighttp.h b/sunshine/confighttp.h index d3b9e85e..edd7181e 100644 --- a/sunshine/confighttp.h +++ b/sunshine/confighttp.h @@ -14,7 +14,7 @@ namespace confighttp { - void start(std::shared_ptr shutdown_event); +void start(std::shared_ptr shutdown_event); } #endif //SUNSHINE_CONFIGHTTP_H diff --git a/sunshine/crypto.cpp b/sunshine/crypto.cpp index a49af9da..58053a03 100644 --- a/sunshine/crypto.cpp +++ b/sunshine/crypto.cpp @@ -6,7 +6,7 @@ #include #include namespace crypto { -using big_num_t = util::safe_ptr; +using big_num_t = util::safe_ptr; //using rsa_t = util::safe_ptr; using asn1_string_t = util::safe_ptr; @@ -340,23 +340,21 @@ void md_ctx_destroy(EVP_MD_CTX *ctx) { EVP_MD_CTX_destroy(ctx); } -std::string rand_string(std::size_t bytes) -{ +std::string rand_string(std::size_t bytes) { std::string alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!%&()=-"; - std::string value = rand(bytes); - for (std::size_t i = 0; i != value.size(); ++i) { + std::string value = rand(bytes); + for(std::size_t i = 0; i != value.size(); ++i) { value[i] = alphabet[value[i] % alphabet.length()]; } return value; } -std::string hash_hexstr(const std::string_view &plaintext) -{ +std::string hash_hexstr(const std::string_view &plaintext) { sha256_t hashBytes = crypto::hash(plaintext); std::ostringstream hashStream; - hashStream << std::hex << std::setfill( '0' ); - std::for_each( hashBytes.cbegin(), hashBytes.cend(), [&]( int c ) { hashStream << std::setw( 2 ) << c; } ); + hashStream << std::hex << std::setfill('0'); + std::for_each(hashBytes.cbegin(), hashBytes.cend(), [&](int c) { hashStream << std::setw(2) << c; }); std::string hashString = hashStream.str(); return hashString; } -} \ No newline at end of file +} // namespace crypto \ No newline at end of file diff --git a/sunshine/crypto.h b/sunshine/crypto.h index ed6373a9..369a417c 100644 --- a/sunshine/crypto.h +++ b/sunshine/crypto.h @@ -7,12 +7,11 @@ #include #include +#include #include #include #include #include -#include -#include #include "utility.h" diff --git a/sunshine/httpcommon.cpp b/sunshine/httpcommon.cpp index b8763ffe..9dda7a00 100644 --- a/sunshine/httpcommon.cpp +++ b/sunshine/httpcommon.cpp @@ -2,9 +2,9 @@ #include +#include #include #include -#include #include @@ -13,187 +13,171 @@ #include #include "config.h" -#include "utility.h" -#include "rtsp.h" #include "crypto.h" +#include "httpcommon.h" +#include "main.h" +#include "network.h" #include "nvhttp.h" #include "platform/common.h" -#include "network.h" +#include "rtsp.h" +#include "utility.h" #include "uuid.h" -#include "main.h" -#include "httpcommon.h" -namespace http -{ - using namespace std::literals; - namespace fs = std::filesystem; - namespace pt = boost::property_tree; +namespace http { +using namespace std::literals; +namespace fs = std::filesystem; +namespace pt = boost::property_tree; - int create_creds(const std::string &pkey, const std::string &cert); - int generate_user_creds(const std::string &file); - int reload_user_creds(const std::string &file); - std::string read_file(const char *path); - int write_file(const char *path, const std::string_view &contents); - std::string unique_id; - net::net_e origin_pin_allowed; - - void init(std::shared_ptr shutdown_event) - { - bool clean_slate = config::sunshine.flags[config::flag::FRESH_STATE]; - origin_pin_allowed = net::from_enum_string(config::nvhttp.origin_pin_allowed); - if (clean_slate) - { - unique_id = util::uuid_t::generate().string(); - auto dir = std::filesystem::temp_directory_path() / "Sushine"sv; - config::nvhttp.cert = (dir / ("cert-"s + unique_id)).string(); - config::nvhttp.pkey = (dir / ("pkey-"s + unique_id)).string(); - } +int create_creds(const std::string &pkey, const std::string &cert); +int generate_user_creds(const std::string &file); +int reload_user_creds(const std::string &file); +std::string read_file(const char *path); +int write_file(const char *path, const std::string_view &contents); +std::string unique_id; +net::net_e origin_pin_allowed; - if (!fs::exists(config::nvhttp.pkey) || !fs::exists(config::nvhttp.cert)) - { - if (create_creds(config::nvhttp.pkey, config::nvhttp.cert)) - { - shutdown_event->raise(true); - return; - } - } - if(!fs::exists(config::sunshine.credentials_file)){ - if(generate_user_creds(config::sunshine.credentials_file)){ - shutdown_event->raise(true); - return; - } - } - if(reload_user_creds(config::sunshine.credentials_file)){ +void init(std::shared_ptr shutdown_event) { + bool clean_slate = config::sunshine.flags[config::flag::FRESH_STATE]; + origin_pin_allowed = net::from_enum_string(config::nvhttp.origin_pin_allowed); + if(clean_slate) { + unique_id = util::uuid_t::generate().string(); + auto dir = std::filesystem::temp_directory_path() / "Sushine"sv; + config::nvhttp.cert = (dir / ("cert-"s + unique_id)).string(); + config::nvhttp.pkey = (dir / ("pkey-"s + unique_id)).string(); + } + + if(!fs::exists(config::nvhttp.pkey) || !fs::exists(config::nvhttp.cert)) { + if(create_creds(config::nvhttp.pkey, config::nvhttp.cert)) { shutdown_event->raise(true); return; } } - - int generate_user_creds(const std::string &file) - { - pt::ptree outputTree; - try { - std::string username = "sunshine"; - std::string plainPassword = crypto::rand_string(16); - std::string salt = crypto::rand_string(16); - outputTree.put("username","sunshine"); - outputTree.put("salt",salt); - outputTree.put("password",crypto::hash_hexstr(plainPassword + salt)); - BOOST_LOG(info) << "New credentials has been created"; - BOOST_LOG(info) << "Username: " << username; - BOOST_LOG(info) << "Password: " << plainPassword; - pt::write_json(file,outputTree); - } catch (std::exception &e){ - BOOST_LOG(fatal) << e.what(); - return 1; + if(!fs::exists(config::sunshine.credentials_file)) { + if(generate_user_creds(config::sunshine.credentials_file)) { + shutdown_event->raise(true); + return; } - return 0; + } + if(reload_user_creds(config::sunshine.credentials_file)) { + shutdown_event->raise(true); + return; + } +} + +int generate_user_creds(const std::string &file) { + pt::ptree outputTree; + try { + std::string username = "sunshine"; + std::string plainPassword = crypto::rand_string(16); + std::string salt = crypto::rand_string(16); + outputTree.put("username", "sunshine"); + outputTree.put("salt", salt); + outputTree.put("password", crypto::hash_hexstr(plainPassword + salt)); + BOOST_LOG(info) << "New credentials has been created"; + BOOST_LOG(info) << "Username: " << username; + BOOST_LOG(info) << "Password: " << plainPassword; + pt::write_json(file, outputTree); + } + catch(std::exception &e) { + BOOST_LOG(fatal) << e.what(); + return 1; + } + return 0; +} + +int reload_user_creds(const std::string &file) { + pt::ptree inputTree; + try { + pt::read_json(file, inputTree); + config::sunshine.username = inputTree.get("username"); + config::sunshine.password = inputTree.get("password"); + config::sunshine.salt = inputTree.get("salt"); + } + catch(std::exception &e) { + BOOST_LOG(fatal) << e.what(); + return 1; + } + return 0; +} + +int create_creds(const std::string &pkey, const std::string &cert) { + fs::path pkey_path = pkey; + fs::path cert_path = cert; + + auto creds = crypto::gen_creds("Sunshine Gamestream Host"sv, 2048); + + auto pkey_dir = pkey_path; + auto cert_dir = cert_path; + pkey_dir.remove_filename(); + cert_dir.remove_filename(); + + std::error_code err_code {}; + fs::create_directories(pkey_dir, err_code); + if(err_code) { + BOOST_LOG(fatal) << "Couldn't create directory ["sv << pkey_dir << "] :"sv << err_code.message(); + return -1; } - int reload_user_creds(const std::string &file) - { - pt::ptree inputTree; - try { - pt::read_json(file, inputTree); - config::sunshine.username = inputTree.get("username"); - config::sunshine.password = inputTree.get("password"); - config::sunshine.salt = inputTree.get("salt"); - } catch(std::exception &e){ - BOOST_LOG(fatal) << e.what(); - return 1; - } - return 0; - } - - int create_creds(const std::string &pkey, const std::string &cert) - { - fs::path pkey_path = pkey; - fs::path cert_path = cert; - - auto creds = crypto::gen_creds("Sunshine Gamestream Host"sv, 2048); - - auto pkey_dir = pkey_path; - auto cert_dir = cert_path; - pkey_dir.remove_filename(); - cert_dir.remove_filename(); - - std::error_code err_code{}; - fs::create_directories(pkey_dir, err_code); - if (err_code) - { - BOOST_LOG(fatal) << "Couldn't create directory ["sv << pkey_dir << "] :"sv << err_code.message(); - return -1; - } - - fs::create_directories(cert_dir, err_code); - if (err_code) - { - BOOST_LOG(fatal) << "Couldn't create directory ["sv << cert_dir << "] :"sv << err_code.message(); - return -1; - } - - if (write_file(pkey.c_str(), creds.pkey)) - { - BOOST_LOG(fatal) << "Couldn't open ["sv << config::nvhttp.pkey << ']'; - return -1; - } - - if (write_file(cert.c_str(), creds.x509)) - { - BOOST_LOG(fatal) << "Couldn't open ["sv << config::nvhttp.cert << ']'; - return -1; - } - - fs::permissions(pkey_path, - fs::perms::owner_read | fs::perms::owner_write, - fs::perm_options::replace, err_code); - - if (err_code) - { - BOOST_LOG(fatal) << "Couldn't change permissions of ["sv << config::nvhttp.pkey << "] :"sv << err_code.message(); - return -1; - } - - fs::permissions(cert_path, - fs::perms::owner_read | fs::perms::group_read | fs::perms::others_read | fs::perms::owner_write, - fs::perm_options::replace, err_code); - - if (err_code) - { - BOOST_LOG(fatal) << "Couldn't change permissions of ["sv << config::nvhttp.cert << "] :"sv << err_code.message(); - return -1; - } - - return 0; - } - int write_file(const char *path, const std::string_view &contents) - { - std::ofstream out(path); - - if (!out.is_open()) - { - return -1; - } - - out << contents; - - return 0; + fs::create_directories(cert_dir, err_code); + if(err_code) { + BOOST_LOG(fatal) << "Couldn't create directory ["sv << cert_dir << "] :"sv << err_code.message(); + return -1; } - std::string read_file(const char *path) - { - std::ifstream in(path); - - std::string input; - std::string base64_cert; - - //FIXME: Being unable to read file could result in infinite loop - while (!in.eof()) - { - std::getline(in, input); - base64_cert += input + '\n'; - } - - return base64_cert; + if(write_file(pkey.c_str(), creds.pkey)) { + BOOST_LOG(fatal) << "Couldn't open ["sv << config::nvhttp.pkey << ']'; + return -1; } -} \ No newline at end of file + + if(write_file(cert.c_str(), creds.x509)) { + BOOST_LOG(fatal) << "Couldn't open ["sv << config::nvhttp.cert << ']'; + return -1; + } + + fs::permissions(pkey_path, + fs::perms::owner_read | fs::perms::owner_write, + fs::perm_options::replace, err_code); + + if(err_code) { + BOOST_LOG(fatal) << "Couldn't change permissions of ["sv << config::nvhttp.pkey << "] :"sv << err_code.message(); + return -1; + } + + fs::permissions(cert_path, + fs::perms::owner_read | fs::perms::group_read | fs::perms::others_read | fs::perms::owner_write, + fs::perm_options::replace, err_code); + + if(err_code) { + BOOST_LOG(fatal) << "Couldn't change permissions of ["sv << config::nvhttp.cert << "] :"sv << err_code.message(); + return -1; + } + + return 0; +} +int write_file(const char *path, const std::string_view &contents) { + std::ofstream out(path); + + if(!out.is_open()) { + return -1; + } + + out << contents; + + return 0; +} + +std::string read_file(const char *path) { + std::ifstream in(path); + + std::string input; + std::string base64_cert; + + //FIXME: Being unable to read file could result in infinite loop + while(!in.eof()) { + std::getline(in, input); + base64_cert += input + '\n'; + } + + return base64_cert; +} +} // namespace http \ No newline at end of file diff --git a/sunshine/httpcommon.h b/sunshine/httpcommon.h index 40cc0a66..4997b2b1 100644 --- a/sunshine/httpcommon.h +++ b/sunshine/httpcommon.h @@ -1,9 +1,9 @@ #include "network.h" -namespace http{ - void init(std::shared_ptr shutdown_event); - int create_creds(const std::string &pkey, const std::string &cert); - std::string read_file(const char *path); - int write_file(const char *path, const std::string_view &contents); - extern std::string unique_id; - extern net::net_e origin_pin_allowed; -} \ No newline at end of file +namespace http { +void init(std::shared_ptr shutdown_event); +int create_creds(const std::string &pkey, const std::string &cert); +std::string read_file(const char *path); +int write_file(const char *path, const std::string_view &contents); +extern std::string unique_id; +extern net::net_e origin_pin_allowed; +} // namespace http \ No newline at end of file diff --git a/sunshine/main.cpp b/sunshine/main.cpp index fd029a72..1d1693ea 100644 --- a/sunshine/main.cpp +++ b/sunshine/main.cpp @@ -15,9 +15,9 @@ #include #include "config.h" -#include "nvhttp.h" -#include "httpcommon.h" #include "confighttp.h" +#include "httpcommon.h" +#include "nvhttp.h" #include "rtsp.h" #include "thread_pool.h" #include "video.h" @@ -126,7 +126,7 @@ int main(int argc, char *argv[]) { }); proc::refresh(config::stream.file_apps); - + auto deinit_guard = platf::init(); if(!deinit_guard) { return 4; diff --git a/sunshine/nvhttp.cpp b/sunshine/nvhttp.cpp index b7d90132..e1dc5c0c 100644 --- a/sunshine/nvhttp.cpp +++ b/sunshine/nvhttp.cpp @@ -20,6 +20,7 @@ #include "config.h" #include "crypto.h" +#include "httpcommon.h" #include "main.h" #include "network.h" #include "nvhttp.h" @@ -27,9 +28,6 @@ #include "rtsp.h" #include "utility.h" #include "uuid.h" -#include "main.h" -#include "httpcommon.h" - namespace nvhttp { @@ -133,7 +131,7 @@ void load_state() { return; } - http::unique_id = root.get("root.uniqueid"); + http::unique_id = root.get("root.uniqueid"); auto device_nodes = root.get_child("root.devices"); for(auto &[_, device_node] : device_nodes) { @@ -731,14 +729,14 @@ void appasset(resp_https_t response, req_https_t request) { } void start(std::shared_ptr shutdown_event) { - + bool clean_slate = config::sunshine.flags[config::flag::FRESH_STATE]; if(!clean_slate) { load_state(); } - conf_intern.pkey = http::read_file(config::nvhttp.pkey.c_str()); + conf_intern.pkey = http::read_file(config::nvhttp.pkey.c_str()); conf_intern.servercert = http::read_file(config::nvhttp.cert.c_str()); auto ctx = std::make_shared(boost::asio::ssl::context::tls); @@ -858,4 +856,4 @@ void start(std::shared_ptr shutdown_event) { ssl.join(); tcp.join(); } -} \ No newline at end of file +} // namespace nvhttp \ No newline at end of file diff --git a/sunshine/nvhttp.h b/sunshine/nvhttp.h index bfa3e119..18aaa969 100644 --- a/sunshine/nvhttp.h +++ b/sunshine/nvhttp.h @@ -5,11 +5,11 @@ #ifndef SUNSHINE_NVHTTP_H #define SUNSHINE_NVHTTP_H -#include -#include +#include "thread_safe.h" #include #include -#include "thread_safe.h" +#include +#include #define CA_DIR SUNSHINE_ASSETS_DIR "/demoCA" #define PRIVATE_KEY_FILE CA_DIR "/cakey.pem" @@ -17,7 +17,8 @@ namespace nvhttp { void start(std::shared_ptr shutdown_event); -template void pin(std::shared_ptr::Response> response, std::shared_ptr::Request> request); -} +template +void pin(std::shared_ptr::Response> response, std::shared_ptr::Request> request); +} // namespace nvhttp #endif //SUNSHINE_NVHTTP_H