Web UI IP Based Authentication

This commit is contained in:
Elia Zammuto 2021-05-17 21:56:55 +02:00
parent fe08c241ec
commit 57f444357d
5 changed files with 30 additions and 6 deletions

View File

@ -35,9 +35,9 @@
<div class="mb-3"> <div class="mb-3">
<label for="origin_pin_allowed" class="form-label">Origin PIN Allowed</label> <label for="origin_pin_allowed" class="form-label">Origin PIN Allowed</label>
<select id="origin_pin_allowed" class="form-control" v-model="config.origin_pin_allowed"> <select id="origin_pin_allowed" class="form-control" v-model="config.origin_pin_allowed">
<option value="pc">Only localhost may access /pin</option> <option value="pc">Only localhost may access /pin and Web UI</option>
<option value="lan">Only those in LAN may access /pin</option> <option value="lan">Only those in LAN may access /pin and Web UI</option>
<option value="wan">Anyone may access /pin</option> <option value="wan">Anyone may access /pin and Web UI</option>
</select> </select>
<div class="form-text">The origin of the remote endpoint address that is not denied for HTTP method /pin <div class="form-text">The origin of the remote endpoint address that is not denied for HTTP method /pin
</div> </div>

View File

@ -49,6 +49,18 @@ enum class op_e
REMOVE REMOVE
}; };
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) {
BOOST_LOG(info) << '[' << address << "] -- denied"sv;
response->write(SimpleWeb::StatusCode::client_error_forbidden);
return false;
}
return true;
}
template <class T> template <class T>
void not_found(std::shared_ptr<typename SimpleWeb::ServerBase<T>::Response> response, std::shared_ptr<typename SimpleWeb::ServerBase<T>::Request> request) void not_found(std::shared_ptr<typename SimpleWeb::ServerBase<T>::Response> response, std::shared_ptr<typename SimpleWeb::ServerBase<T>::Request> request)
{ {
@ -66,6 +78,7 @@ void not_found(std::shared_ptr<typename SimpleWeb::ServerBase<T>::Response> resp
void getIndexPage(resp_https_t response, req_https_t request) 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 header = read_file(WEB_DIR "header.html");
std::string content = read_file(WEB_DIR "index.html"); std::string content = read_file(WEB_DIR "index.html");
response->write(header + content); response->write(header + content);
@ -74,6 +87,7 @@ void getIndexPage(resp_https_t response, req_https_t request)
template <class T> template <class T>
void getPinPage(std::shared_ptr<typename SimpleWeb::ServerBase<T>::Response> response, std::shared_ptr<typename SimpleWeb::ServerBase<T>::Request> request) void getPinPage(std::shared_ptr<typename SimpleWeb::ServerBase<T>::Response> response, std::shared_ptr<typename SimpleWeb::ServerBase<T>::Request> request)
{ {
if(!authenticate(response,request))return;
std::string header = read_file(WEB_DIR "header.html"); std::string header = read_file(WEB_DIR "header.html");
std::string content = read_file(WEB_DIR "pin.html"); std::string content = read_file(WEB_DIR "pin.html");
response->write(header + content); response->write(header + content);
@ -82,6 +96,7 @@ void getPinPage(std::shared_ptr<typename SimpleWeb::ServerBase<T>::Response> res
template <class T> template <class T>
void getAppsPage(std::shared_ptr<typename SimpleWeb::ServerBase<T>::Response> response, std::shared_ptr<typename SimpleWeb::ServerBase<T>::Request> request) void getAppsPage(std::shared_ptr<typename SimpleWeb::ServerBase<T>::Response> response, std::shared_ptr<typename SimpleWeb::ServerBase<T>::Request> request)
{ {
if(!authenticate(response,request))return;
std::string header = read_file(WEB_DIR "header.html"); std::string header = read_file(WEB_DIR "header.html");
std::string content = read_file(WEB_DIR "apps.html"); std::string content = read_file(WEB_DIR "apps.html");
response->write(header + content); response->write(header + content);
@ -90,6 +105,7 @@ void getAppsPage(std::shared_ptr<typename SimpleWeb::ServerBase<T>::Response> re
template <class T> template <class T>
void getClientsPage(std::shared_ptr<typename SimpleWeb::ServerBase<T>::Response> response, std::shared_ptr<typename SimpleWeb::ServerBase<T>::Request> request) void getClientsPage(std::shared_ptr<typename SimpleWeb::ServerBase<T>::Response> response, std::shared_ptr<typename SimpleWeb::ServerBase<T>::Request> request)
{ {
if(!authenticate(response,request))return;
std::string header = read_file(WEB_DIR "header.html"); std::string header = read_file(WEB_DIR "header.html");
std::string content = read_file(WEB_DIR "clients.html"); std::string content = read_file(WEB_DIR "clients.html");
response->write(header + content); response->write(header + content);
@ -98,6 +114,7 @@ void getClientsPage(std::shared_ptr<typename SimpleWeb::ServerBase<T>::Response>
template <class T> template <class T>
void getConfigPage(std::shared_ptr<typename SimpleWeb::ServerBase<T>::Response> response, std::shared_ptr<typename SimpleWeb::ServerBase<T>::Request> request) void getConfigPage(std::shared_ptr<typename SimpleWeb::ServerBase<T>::Response> response, std::shared_ptr<typename SimpleWeb::ServerBase<T>::Request> request)
{ {
if(!authenticate(response,request))return;
std::string header = read_file(WEB_DIR "header.html"); std::string header = read_file(WEB_DIR "header.html");
std::string content = read_file(WEB_DIR "config.html"); std::string content = read_file(WEB_DIR "config.html");
response->write(header + content); response->write(header + content);
@ -105,12 +122,14 @@ void getConfigPage(std::shared_ptr<typename SimpleWeb::ServerBase<T>::Response>
void getApps(resp_https_t response, req_https_t request) 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); std::string content = read_file(SUNSHINE_ASSETS_DIR "/" APPS_JSON);
response->write(content); response->write(content);
} }
void saveApp(resp_https_t response, req_https_t request) void saveApp(resp_https_t response, req_https_t request)
{ {
if(!authenticate(response,request))return;
std::stringstream ss; std::stringstream ss;
ss << request->content.rdbuf(); ss << request->content.rdbuf();
pt::ptree outputTree; pt::ptree outputTree;
@ -171,6 +190,7 @@ void saveApp(resp_https_t response, req_https_t request)
void deleteApp(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; pt::ptree outputTree;
auto g = util::fail_guard([&]() { auto g = util::fail_guard([&]() {
std::ostringstream data; std::ostringstream data;
@ -222,6 +242,7 @@ void deleteApp(resp_https_t response, req_https_t request)
void getConfig(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; pt::ptree outputTree;
auto g = util::fail_guard([&]() { auto g = util::fail_guard([&]() {
std::ostringstream data; std::ostringstream data;
@ -261,6 +282,7 @@ void getConfig(resp_https_t response, req_https_t request)
void saveConfig(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 ss;
std::stringstream configStream; std::stringstream configStream;
ss << request->content.rdbuf(); ss << request->content.rdbuf();

View File

@ -32,10 +32,12 @@ namespace http
std::string read_file(const char *path); std::string read_file(const char *path);
int write_file(const char *path, const std::string_view &contents); int write_file(const char *path, const std::string_view &contents);
std::string unique_id; std::string unique_id;
net::net_e origin_pin_allowed;
void init(std::shared_ptr<safe::signal_t> shutdown_event) void init(std::shared_ptr<safe::signal_t> shutdown_event)
{ {
bool clean_slate = config::sunshine.flags[config::flag::FRESH_STATE]; 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) if (clean_slate)
{ {
unique_id = util::uuid_t::generate().string(); unique_id = util::uuid_t::generate().string();

View File

@ -1,7 +1,9 @@
#include "network.h"
namespace http{ namespace http{
void init(std::shared_ptr<safe::signal_t> shutdown_event); void init(std::shared_ptr<safe::signal_t> shutdown_event);
int create_creds(const std::string &pkey, const std::string &cert); int create_creds(const std::string &pkey, const std::string &cert);
std::string read_file(const char *path); std::string read_file(const char *path);
int write_file(const char *path, const std::string_view &contents); int write_file(const char *path, const std::string_view &contents);
extern std::string unique_id; extern std::string unique_id;
extern net::net_e origin_pin_allowed;
} }

View File

@ -76,7 +76,6 @@ struct pair_session_t {
// uniqueID, session // uniqueID, session
std::unordered_map<std::string, pair_session_t> map_id_sess; std::unordered_map<std::string, pair_session_t> map_id_sess;
std::unordered_map<std::string, client_t> map_id_client; std::unordered_map<std::string, client_t> map_id_client;
net::net_e origin_pin_allowed;
using args_t = SimpleWeb::CaseInsensitiveMultimap; using args_t = SimpleWeb::CaseInsensitiveMultimap;
using resp_https_t = std::shared_ptr<typename SimpleWeb::ServerBase<SimpleWeb::HTTPS>::Response>; using resp_https_t = std::shared_ptr<typename SimpleWeb::ServerBase<SimpleWeb::HTTPS>::Response>;
@ -405,7 +404,7 @@ void pin(std::shared_ptr<typename SimpleWeb::ServerBase<T>::Response> response,
auto address = request->remote_endpoint_address(); auto address = request->remote_endpoint_address();
auto ip_type = net::from_address(address); auto ip_type = net::from_address(address);
if(ip_type > origin_pin_allowed) { if(ip_type > http::origin_pin_allowed) {
BOOST_LOG(info) << '[' << address << "] -- denied"sv; BOOST_LOG(info) << '[' << address << "] -- denied"sv;
response->write(SimpleWeb::StatusCode::client_error_forbidden); response->write(SimpleWeb::StatusCode::client_error_forbidden);
@ -677,7 +676,6 @@ void appasset(resp_https_t response, req_https_t request) {
void start(std::shared_ptr<safe::signal_t> shutdown_event) { void start(std::shared_ptr<safe::signal_t> shutdown_event) {
bool clean_slate = config::sunshine.flags[config::flag::FRESH_STATE]; 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) { if(!clean_slate) {
load_state(); load_state();