This commit is contained in:
billz 2023-09-13 21:26:19 +02:00
parent 7831afa29a
commit 1e5ac9b3fc
9 changed files with 184 additions and 53 deletions

1
.gitignore vendored
View file

@ -4,3 +4,4 @@ yarn-error.log
*.swp
includes/config.php
rootCA.pem
vendor

View file

@ -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)) {

136
app/lib/Auth.php Normal file
View 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']);
}
}

View file

@ -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"
)
);
}

View file

@ -1,22 +1,16 @@
<?php
$user = $_SERVER['PHP_AUTH_USER'] ?? "";
$pass = $_SERVER['PHP_AUTH_PW'] ?? "";
require_once RASPI_CONFIG.'/raspap.php';
$config = getConfig();
if (RASPI_AUTH_ENABLED) {
$validated = ($user == $config['admin_user']) && password_verify($pass, $config['admin_pass']);
if (!$validated) {
header('WWW-Authenticate: Basic realm="RaspAP"');
if (function_exists('http_response_code')) {
// http_response_code will respond with proper HTTP version back.
http_response_code(401);
$user = $_SERVER['PHP_AUTH_USER'] ?? '';
$pass = $_SERVER['PHP_AUTH_PW'] ?? '';
$auth = new \RaspAP\Authenticate\HTTPAuth;
if (!$auth->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;
}

View file

@ -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;

View file

@ -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();
<!-- Nav Item - User -->
<li class="nav-item dropdown no-arrow">
<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>
</a>
</li>
@ -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();

View file

@ -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;
}

View file

@ -21,20 +21,35 @@
</div>
<div class="row">
<div class="form-group col-md-6">
<label for="password"><?php echo _("Old password"); ?></label>
<input type="password" class="form-control" name="oldpass"/>
<div class="mb-2"><?php echo _("Old password"); ?></div>
<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 class="row">
<div class="form-group col-md-6">
<label for="password"><?php echo _("New password"); ?></label>
<input type="password" class="form-control" name="newpass"/>
<div class="mb-2"><?php echo _("New password"); ?></div>
<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 class="row">
<div class="form-group col-md-6">
<label for="password"><?php echo _("Repeat new password"); ?></label>
<input type="password" class="form-control" name="newpassagain"/>
<div class="mb-2"><?php echo _("Repeat new password"); ?></div>
<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>
<input type="submit" class="btn btn-outline btn-primary" name="UpdateAdminPassword" value="<?php echo _("Save settings"); ?>" />