From 1e5ac9b3fc91fbb4aeeef4faecd453e64e01227e Mon Sep 17 00:00:00 2001 From: billz Date: Wed, 13 Sep 2023 21:26:19 +0200 Subject: [PATCH] Apply patch from RaspAP/raspap-insiders#209 --- .gitignore | 1 + ajax/bandwidth/get_bandwidth.php | 6 -- app/lib/Auth.php | 136 +++++++++++++++++++++++++++++++ includes/admin.php | 13 ++- includes/authenticate.php | 24 ++---- includes/functions.php | 4 +- index.php | 7 +- raspap.php | 19 ----- templates/admin.php | 27 ++++-- 9 files changed, 184 insertions(+), 53 deletions(-) create mode 100644 app/lib/Auth.php delete mode 100755 raspap.php diff --git a/.gitignore b/.gitignore index 1dd450a5..a2a77b49 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ yarn-error.log *.swp includes/config.php rootCA.pem +vendor diff --git a/ajax/bandwidth/get_bandwidth.php b/ajax/bandwidth/get_bandwidth.php index 4fcf8057..70e9b882 100644 --- a/ajax/bandwidth/get_bandwidth.php +++ b/ajax/bandwidth/get_bandwidth.php @@ -3,12 +3,6 @@ require '../../includes/csrf.php'; require_once '../../includes/config.php'; -require_once RASPI_CONFIG.'/raspap.php'; - -header('X-Frame-Options: DENY'); -header("Content-Security-Policy: default-src 'none'; connect-src 'self'"); -require_once '../../includes/authenticate.php'; - $interface = filter_input(INPUT_GET, 'inet', FILTER_SANITIZE_SPECIAL_CHARS); if (empty($interface)) { diff --git a/app/lib/Auth.php b/app/lib/Auth.php new file mode 100644 index 00000000..5e85d3df --- /dev/null +++ b/app/lib/Auth.php @@ -0,0 +1,136 @@ + + * @license https://github.com/raspap/raspap-webgui/blob/master/LICENSE + * @see https://www.php.net/manual/en/features.http-auth.php + */ + +declare(strict_types=1); + +namespace RaspAP\Authenticate; + +class HTTPAuth +{ + + /** + * @var string $realm + */ + public $realm = 'Authentication Required'; + + /** + * Stored login credentials + * @var array $auth_config + */ + protected $auth_config; + + /** + * Default login credentials + * @var array $auth_default + */ + private $auth_default = array( + 'admin_user' => 'admin', + 'admin_pass' => '$2y$10$YKIyWAmnQLtiJAy6QgHQ.eCpY4m.HCEbiHaTgN6.acNC6bDElzt.i' + ); + + // Constructor + public function __construct() + { + $this->auth_config = $this->getAuthConfig(); + } + + /* + * Determines if user is logged in + * return boolean + */ + public function isLogged() + { + return isset($_SESSION['user_id']); + } + + /* + * Authenticate a user using HTTP basic auth + */ + public function authenticate() + { + if (!$this->isLogged()) { + header('HTTP/1.0 401 Unauthorized'); + header('WWW-Authenticate: Basic realm="'.$this->realm.'"'); + if (function_exists('http_response_code')) { + // http_response_code will respond with proper HTTP version + http_response_code(401); + } else { + header('HTTP/1.0 401 Unauthorized'); + } + exit('Not authorized'.PHP_EOL); + } + } + + /* + * Attempt to login a user with supplied credentials + * @var string $user + * @var string $pass + * return boolean + */ + public function login(string $user, string $pass) + { + if ($this->isValidCredentials($user, $pass)) { + $_SESSION['user_id'] = $user; + return true; + } + return false; + } + + /* + * Gets the current authentication config + * return array $config + */ + public function getAuthConfig() + { + $config = $this->auth_default; + + if (file_exists(RASPI_CONFIG . '/raspap.auth')) { + if ($auth_details = fopen(RASPI_CONFIG . '/raspap.auth', 'r')) { + $config['admin_user'] = trim(fgets($auth_details)); + $config['admin_pass'] = trim(fgets($auth_details)); + fclose($auth_details); + } + } + return $config; + } + + /* + * Validates a set of credentials + * @var string $user + * @var string $pass + * return boolean + */ + protected function isValidCredentials(string $user, string $pass) + { + return $this->validateUser($user) && $this->validatePassword($pass); + } + + /** + * Validates a user + * + * @param string $user + */ + protected function validateUser(string $user) + { + return $user == $this->auth_config['admin_user']; + } + + /** + * Validates a password + * + * @param string $pass + */ + protected function validatePassword(string $pass) + { + return password_verify($pass, $this->auth_config['admin_pass']); + } + +} diff --git a/includes/admin.php b/includes/admin.php index ffe32e77..68fec422 100755 --- a/includes/admin.php +++ b/includes/admin.php @@ -2,9 +2,13 @@ require_once 'includes/status_messages.php'; -function DisplayAuthConfig($username, $password) +function DisplayAuthConfig($username) { $status = new StatusMessages(); + $auth = new \RaspAP\Authenticate\HTTPAuth; + $config = $auth->getAuthConfig(); + $password = $config['admin_pass']; + if (isset($_POST['UpdateAdminPassword'])) { if (password_verify($_POST['oldpass'], $password)) { $new_username=trim($_POST['username']); @@ -33,5 +37,10 @@ function DisplayAuthConfig($username, $password) } } - echo renderTemplate("admin", compact("status", "username")); + echo renderTemplate( + "admin", compact( + "status", + "username" + ) + ); } diff --git a/includes/authenticate.php b/includes/authenticate.php index 3059ff42..3f676be5 100755 --- a/includes/authenticate.php +++ b/includes/authenticate.php @@ -1,22 +1,16 @@ isLogged()) { + if ($auth->login($user, $pass)) { + $config = $auth->getAuthConfig(); } else { - header('HTTP/1.0 401 Unauthorized'); + $auth->authenticate(); } - exit('Not authorized'.PHP_EOL); } -} else { - $validated = true; } diff --git a/includes/functions.php b/includes/functions.php index ca264ff7..3b44b1e4 100755 --- a/includes/functions.php +++ b/includes/functions.php @@ -668,6 +668,7 @@ function getThemeOpt() { if (!isset($_COOKIE['theme'])) { $theme = "custom.php"; + setcookie('theme', $theme); } else { $theme = $_COOKIE['theme']; } @@ -680,6 +681,7 @@ function getColorOpt() $color = "#2b8080"; } else { $color = $_COOKIE['color']; + setcookie('color', $color); } return $color; } @@ -737,7 +739,7 @@ function validate_host($host) // @return boolean function getNightmode() { - if ($_COOKIE['theme'] == 'lightsout.css') { + if (isset($_COOKIE['theme']) && $_COOKIE['theme'] == 'lightsout.css') { return true; } else { return false; diff --git a/index.php b/index.php index 96a45900..a10faa67 100755 --- a/index.php +++ b/index.php @@ -27,8 +27,8 @@ require 'includes/csrf.php'; ensureCSRFSessionToken(); require_once 'includes/config.php'; +require_once 'app/lib/Auth.php'; require_once 'includes/defaults.php'; -require_once RASPI_CONFIG.'/raspap.php'; require_once 'includes/locale.php'; require_once 'includes/functions.php'; require_once 'includes/dashboard.php'; @@ -47,7 +47,6 @@ require_once 'includes/openvpn.php'; require_once 'includes/wireguard.php'; require_once 'includes/torproxy.php'; -$config = getConfig(); $output = $return = 0; $page = $_SERVER['PATH_INFO']; @@ -232,7 +231,7 @@ $bridgedEnabled = getBridgedState(); @@ -276,7 +275,7 @@ $bridgedEnabled = getBridgedState(); DisplayTorProxyConfig(); break; case "/auth_conf": - DisplayAuthConfig($config['admin_user'], $config['admin_pass']); + DisplayAuthConfig($_SESSION['user_id']); break; case "/save_hostapd_conf": SaveTORAndVPNConfig(); diff --git a/raspap.php b/raspap.php deleted file mode 100755 index e45e3eb4..00000000 --- a/raspap.php +++ /dev/null @@ -1,19 +0,0 @@ - 'admin', - 'admin_pass' => '$2y$10$YKIyWAmnQLtiJAy6QgHQ.eCpY4m.HCEbiHaTgN6.acNC6bDElzt.i' - ); - - if (file_exists(RASPI_CONFIG . '/raspap.auth')) { - if ($auth_details = fopen(RASPI_CONFIG . '/raspap.auth', 'r')) { - $config['admin_user'] = trim(fgets($auth_details)); - $config['admin_pass'] = trim(fgets($auth_details)); - fclose($auth_details); - } - } - return $config; -} - diff --git a/templates/admin.php b/templates/admin.php index f6ea44c2..490a71f6 100755 --- a/templates/admin.php +++ b/templates/admin.php @@ -21,20 +21,35 @@
- - +
+
+ +
+ +
+
- - +
+
+ +
+ +
+
- - +
+
+ +
+ +
+
" />