mirror of
https://github.com/billz/raspap-webgui.git
synced 2023-10-10 13:37:24 +02:00
Apply patch from RaspAP/raspap-insiders#209
This commit is contained in:
parent
7831afa29a
commit
1e5ac9b3fc
1
.gitignore
vendored
1
.gitignore
vendored
@ -4,3 +4,4 @@ yarn-error.log
|
|||||||
*.swp
|
*.swp
|
||||||
includes/config.php
|
includes/config.php
|
||||||
rootCA.pem
|
rootCA.pem
|
||||||
|
vendor
|
||||||
|
@ -3,12 +3,6 @@
|
|||||||
require '../../includes/csrf.php';
|
require '../../includes/csrf.php';
|
||||||
|
|
||||||
require_once '../../includes/config.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);
|
$interface = filter_input(INPUT_GET, 'inet', FILTER_SANITIZE_SPECIAL_CHARS);
|
||||||
if (empty($interface)) {
|
if (empty($interface)) {
|
||||||
|
136
app/lib/Auth.php
Normal file
136
app/lib/Auth.php
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Authentication class
|
||||||
|
*
|
||||||
|
* @description Basic HTTP authentication class for RaspAP
|
||||||
|
* @author Bill Zimmerman <billzimmerman@gmail.com>
|
||||||
|
* @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']);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -2,9 +2,13 @@
|
|||||||
|
|
||||||
require_once 'includes/status_messages.php';
|
require_once 'includes/status_messages.php';
|
||||||
|
|
||||||
function DisplayAuthConfig($username, $password)
|
function DisplayAuthConfig($username)
|
||||||
{
|
{
|
||||||
$status = new StatusMessages();
|
$status = new StatusMessages();
|
||||||
|
$auth = new \RaspAP\Authenticate\HTTPAuth;
|
||||||
|
$config = $auth->getAuthConfig();
|
||||||
|
$password = $config['admin_pass'];
|
||||||
|
|
||||||
if (isset($_POST['UpdateAdminPassword'])) {
|
if (isset($_POST['UpdateAdminPassword'])) {
|
||||||
if (password_verify($_POST['oldpass'], $password)) {
|
if (password_verify($_POST['oldpass'], $password)) {
|
||||||
$new_username=trim($_POST['username']);
|
$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"
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,22 +1,16 @@
|
|||||||
<?php
|
<?php
|
||||||
$user = $_SERVER['PHP_AUTH_USER'] ?? "";
|
|
||||||
$pass = $_SERVER['PHP_AUTH_PW'] ?? "";
|
|
||||||
|
|
||||||
require_once RASPI_CONFIG.'/raspap.php';
|
|
||||||
$config = getConfig();
|
|
||||||
|
|
||||||
if (RASPI_AUTH_ENABLED) {
|
if (RASPI_AUTH_ENABLED) {
|
||||||
$validated = ($user == $config['admin_user']) && password_verify($pass, $config['admin_pass']);
|
$user = $_SERVER['PHP_AUTH_USER'] ?? '';
|
||||||
if (!$validated) {
|
$pass = $_SERVER['PHP_AUTH_PW'] ?? '';
|
||||||
header('WWW-Authenticate: Basic realm="RaspAP"');
|
|
||||||
if (function_exists('http_response_code')) {
|
$auth = new \RaspAP\Authenticate\HTTPAuth;
|
||||||
// http_response_code will respond with proper HTTP version back.
|
|
||||||
http_response_code(401);
|
if (!$auth->isLogged()) {
|
||||||
|
if ($auth->login($user, $pass)) {
|
||||||
|
$config = $auth->getAuthConfig();
|
||||||
} else {
|
} else {
|
||||||
header('HTTP/1.0 401 Unauthorized');
|
$auth->authenticate();
|
||||||
}
|
}
|
||||||
exit('Not authorized'.PHP_EOL);
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
$validated = true;
|
|
||||||
}
|
}
|
||||||
|
@ -668,6 +668,7 @@ function getThemeOpt()
|
|||||||
{
|
{
|
||||||
if (!isset($_COOKIE['theme'])) {
|
if (!isset($_COOKIE['theme'])) {
|
||||||
$theme = "custom.php";
|
$theme = "custom.php";
|
||||||
|
setcookie('theme', $theme);
|
||||||
} else {
|
} else {
|
||||||
$theme = $_COOKIE['theme'];
|
$theme = $_COOKIE['theme'];
|
||||||
}
|
}
|
||||||
@ -680,6 +681,7 @@ function getColorOpt()
|
|||||||
$color = "#2b8080";
|
$color = "#2b8080";
|
||||||
} else {
|
} else {
|
||||||
$color = $_COOKIE['color'];
|
$color = $_COOKIE['color'];
|
||||||
|
setcookie('color', $color);
|
||||||
}
|
}
|
||||||
return $color;
|
return $color;
|
||||||
}
|
}
|
||||||
@ -737,7 +739,7 @@ function validate_host($host)
|
|||||||
// @return boolean
|
// @return boolean
|
||||||
function getNightmode()
|
function getNightmode()
|
||||||
{
|
{
|
||||||
if ($_COOKIE['theme'] == 'lightsout.css') {
|
if (isset($_COOKIE['theme']) && $_COOKIE['theme'] == 'lightsout.css') {
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
|
@ -27,8 +27,8 @@ require 'includes/csrf.php';
|
|||||||
ensureCSRFSessionToken();
|
ensureCSRFSessionToken();
|
||||||
|
|
||||||
require_once 'includes/config.php';
|
require_once 'includes/config.php';
|
||||||
|
require_once 'app/lib/Auth.php';
|
||||||
require_once 'includes/defaults.php';
|
require_once 'includes/defaults.php';
|
||||||
require_once RASPI_CONFIG.'/raspap.php';
|
|
||||||
require_once 'includes/locale.php';
|
require_once 'includes/locale.php';
|
||||||
require_once 'includes/functions.php';
|
require_once 'includes/functions.php';
|
||||||
require_once 'includes/dashboard.php';
|
require_once 'includes/dashboard.php';
|
||||||
@ -47,7 +47,6 @@ require_once 'includes/openvpn.php';
|
|||||||
require_once 'includes/wireguard.php';
|
require_once 'includes/wireguard.php';
|
||||||
require_once 'includes/torproxy.php';
|
require_once 'includes/torproxy.php';
|
||||||
|
|
||||||
$config = getConfig();
|
|
||||||
$output = $return = 0;
|
$output = $return = 0;
|
||||||
$page = $_SERVER['PATH_INFO'];
|
$page = $_SERVER['PATH_INFO'];
|
||||||
|
|
||||||
@ -232,7 +231,7 @@ $bridgedEnabled = getBridgedState();
|
|||||||
<!-- Nav Item - User -->
|
<!-- Nav Item - User -->
|
||||||
<li class="nav-item dropdown no-arrow">
|
<li class="nav-item dropdown no-arrow">
|
||||||
<a class="nav-link" href="auth_conf">
|
<a class="nav-link" href="auth_conf">
|
||||||
<span class="mr-2 d-none d-lg-inline small"><?php echo htmlspecialchars($config['admin_user'], ENT_QUOTES); ?></span>
|
<span class="mr-2 d-none d-lg-inline small"><?php echo htmlspecialchars($_SESSION['user_id'], ENT_QUOTES); ?></span>
|
||||||
<i class="fas fa-user-circle fa-3x"></i>
|
<i class="fas fa-user-circle fa-3x"></i>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
@ -276,7 +275,7 @@ $bridgedEnabled = getBridgedState();
|
|||||||
DisplayTorProxyConfig();
|
DisplayTorProxyConfig();
|
||||||
break;
|
break;
|
||||||
case "/auth_conf":
|
case "/auth_conf":
|
||||||
DisplayAuthConfig($config['admin_user'], $config['admin_pass']);
|
DisplayAuthConfig($_SESSION['user_id']);
|
||||||
break;
|
break;
|
||||||
case "/save_hostapd_conf":
|
case "/save_hostapd_conf":
|
||||||
SaveTORAndVPNConfig();
|
SaveTORAndVPNConfig();
|
||||||
|
19
raspap.php
19
raspap.php
@ -1,19 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
function getConfig()
|
|
||||||
{
|
|
||||||
$config = array(
|
|
||||||
'admin_user' => '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;
|
|
||||||
}
|
|
||||||
|
|
@ -21,20 +21,35 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="form-group col-md-6">
|
<div class="form-group col-md-6">
|
||||||
<label for="password"><?php echo _("Old password"); ?></label>
|
<div class="mb-2"><?php echo _("Old password"); ?></div>
|
||||||
<input type="password" class="form-control" name="oldpass"/>
|
<div class="input-group">
|
||||||
|
<input type="password" class="form-control" name="oldpass"/>
|
||||||
|
<div class="input-group-append">
|
||||||
|
<button class="btn btn-light js-toggle-password" type="button" data-target="[name=oldpass]" data-toggle-with="fas fa-eye mx-2"><i class="fas fa-eye-slash"></i></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="form-group col-md-6">
|
<div class="form-group col-md-6">
|
||||||
<label for="password"><?php echo _("New password"); ?></label>
|
<div class="mb-2"><?php echo _("New password"); ?></div>
|
||||||
<input type="password" class="form-control" name="newpass"/>
|
<div class="input-group">
|
||||||
|
<input type="password" class="form-control" name="newpass"/>
|
||||||
|
<div class="input-group-append">
|
||||||
|
<button class="btn btn-light js-toggle-password" type="button" data-target="[name=newpass]" data-toggle-with="fas fa-eye mx-2"><i class="fas fa-eye-slash"></i></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="form-group col-md-6">
|
<div class="form-group col-md-6">
|
||||||
<label for="password"><?php echo _("Repeat new password"); ?></label>
|
<div class="mb-2"><?php echo _("Repeat new password"); ?></div>
|
||||||
<input type="password" class="form-control" name="newpassagain"/>
|
<div class="input-group">
|
||||||
|
<input type="password" class="form-control" name="newpassagain"/>
|
||||||
|
<div class="input-group-append">
|
||||||
|
<button class="btn btn-light js-toggle-password" type="button" data-target="[name=newpassagain]" data-toggle-with="fas fa-eye mx-2"><i class="fas fa-eye-slash"></i></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<input type="submit" class="btn btn-outline btn-primary" name="UpdateAdminPassword" value="<?php echo _("Save settings"); ?>" />
|
<input type="submit" class="btn btn-outline btn-primary" name="UpdateAdminPassword" value="<?php echo _("Save settings"); ?>" />
|
||||||
|
Loading…
Reference in New Issue
Block a user