109 lines
3.5 KiB
PHP
109 lines
3.5 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
|
|
$secure = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off');
|
|
session_set_cookie_params([
|
|
'lifetime' => 0,
|
|
'path' => '/',
|
|
'domain' => '',
|
|
'secure' => $secure,
|
|
'httponly' => true,
|
|
'samesite' => 'Strict',
|
|
]);
|
|
ini_set('session.use_strict_mode', '1');
|
|
ini_set('session.cookie_httponly', '1');
|
|
session_name('torpanel');
|
|
session_start();
|
|
|
|
const APP_CONF_DIR = '/etc/torpanel';
|
|
const APP_CONF_FILE = APP_CONF_DIR . '/app.json';
|
|
const STATE_DIR = '/var/lib/torpanel';
|
|
const LOGIN_THROTTLE_FILE = STATE_DIR . '/login_throttle.json';
|
|
const SESSION_IDLE_TTL = 60 * 60 * 12;
|
|
|
|
if (!empty($_SESSION['last']) && (time() - (int)$_SESSION['last']) > SESSION_IDLE_TTL) {
|
|
$_SESSION = [];
|
|
if (ini_get('session.use_cookies')) {
|
|
$p = session_get_cookie_params();
|
|
setcookie(session_name(), '', time() - 42000, $p['path'], $p['domain'], $p['secure'] ?? false, $p['httponly'] ?? true);
|
|
}
|
|
session_destroy();
|
|
session_start();
|
|
}
|
|
$_SESSION['last'] = time();
|
|
|
|
function app_is_installed(): bool {
|
|
return is_file(APP_CONF_FILE);
|
|
}
|
|
function app_config(): array {
|
|
if (!app_is_installed()) return [];
|
|
$raw = @file_get_contents(APP_CONF_FILE);
|
|
return $raw ? (json_decode($raw, true) ?: []) : [];
|
|
}
|
|
function app_save_config(array $cfg): void {
|
|
if (!is_dir(APP_CONF_DIR)) mkdir(APP_CONF_DIR, 0770, true);
|
|
$tmp = APP_CONF_FILE . '.tmp';
|
|
file_put_contents($tmp, json_encode($cfg, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
|
|
rename($tmp, APP_CONF_FILE);
|
|
@chmod(APP_CONF_FILE, 0640);
|
|
}
|
|
|
|
function auth_login(string $u, string $p): bool {
|
|
$cfg = app_config();
|
|
if (!isset($cfg['admin_user'], $cfg['admin_pass'])) return false;
|
|
if (!hash_equals($cfg['admin_user'], $u)) return false;
|
|
if (!password_verify($p, $cfg['admin_pass'])) return false;
|
|
session_regenerate_id(true);
|
|
$_SESSION['uid'] = $u;
|
|
$_SESSION['ua'] = substr($_SERVER['HTTP_USER_AGENT'] ?? '', 0, 160);
|
|
$_SESSION['last'] = time();
|
|
return true;
|
|
}
|
|
function auth_logout(): void {
|
|
$_SESSION = [];
|
|
if (ini_get('session.use_cookies')) {
|
|
$p = session_get_cookie_params();
|
|
setcookie(session_name(), '', time() - 42000, $p['path'], $p['domain'], $p['secure'] ?? false, $p['httponly'] ?? true);
|
|
}
|
|
session_destroy();
|
|
}
|
|
function auth_require(): void {
|
|
if (!app_is_installed()) { header('Location: /setup.php'); exit; }
|
|
if (empty($_SESSION['uid'])) { header('Location: /login.php'); exit; }
|
|
}
|
|
|
|
|
|
function throttle_state(): array {
|
|
if (!is_dir(STATE_DIR)) @mkdir(STATE_DIR, 0775, true);
|
|
$raw = @file_get_contents(LOGIN_THROTTLE_FILE);
|
|
return $raw ? (json_decode($raw, true) ?: []) : [];
|
|
}
|
|
function throttle_save(array $st): void {
|
|
$tmp = LOGIN_THROTTLE_FILE . '.tmp';
|
|
file_put_contents($tmp, json_encode($st));
|
|
@chmod($tmp, 0660);
|
|
rename($tmp, LOGIN_THROTTLE_FILE);
|
|
}
|
|
function throttle_check(string $ip): int {
|
|
$st = throttle_state();
|
|
$now = time();
|
|
$key = $ip ?: 'unknown';
|
|
$rec = $st[$key] ?? ['fails'=>0, 'until'=>0];
|
|
if ($rec['until'] > $now) return $rec['until'] - $now;
|
|
return 0;
|
|
}
|
|
function throttle_record(string $ip, bool $ok): void {
|
|
$st = throttle_state();
|
|
$now = time();
|
|
$key = $ip ?: 'unknown';
|
|
$rec = $st[$key] ?? ['fails'=>0, 'until'=>0];
|
|
if ($ok) {
|
|
$rec = ['fails'=>0, 'until'=>0];
|
|
} else {
|
|
$rec['fails'] = min(10, ($rec['fails'] ?? 0) + 1);
|
|
$wait = min(300, 2 ** $rec['fails']);
|
|
$rec['until'] = $now + $wait;
|
|
}
|
|
$st[$key] = $rec;
|
|
throttle_save($st);
|
|
} |