diff --git a/engine/request.php b/engine/request.php index 1af2f0c..e0f3361 100644 --- a/engine/request.php +++ b/engine/request.php @@ -214,14 +214,13 @@ function input(string $input, array $options = []): array { return $ret; } -function csrf_get(string $key): string { return _csrf_get_token($_SERVER['REMOTE_ADDR'], $key); } -function csrf_check(string $key) { - if (csrf_get($key) != ($_REQUEST['token'] ?? '')) { - forbidden('invalid token'); - } +function csrf_get(string $key): string { + global $AdminSession, $config; + $user_key = is_admin() ? $AdminSession->csrfSalt : $_SERVER['REMOTE_ADDR']; + return substr(hash('sha256', $config['csrf_token'].$user_key.$key), 0, 20); } -function _csrf_get_token(string $user_token, string $key): string { - global $config; - return substr(sha1($config['csrf_token'].$user_token.$key), 0, 20); +function csrf_check(string $key) { + if (csrf_get($key) != ($_REQUEST['token'] ?? '')) + forbidden('invalid token'); } \ No newline at end of file diff --git a/handler/AdminHandler.php b/handler/AdminHandler.php index 0ba1918..ee6e315 100644 --- a/handler/AdminHandler.php +++ b/handler/AdminHandler.php @@ -14,10 +14,11 @@ class AdminHandler extends request_handler { } function GET_index() { - $admin_info = admin_current_info(); + global $AdminSession; + //$admin_info = admin_current_info(); set_title('$admin_title'); render('admin/index', - admin_login: $admin_info['login']); + admin_login: $AdminSession->login); } function GET_login() { diff --git a/lib/AdminActions/Util/Logger.php b/lib/AdminActions/Util/Logger.php index 5f5e460..1de086c 100644 --- a/lib/AdminActions/Util/Logger.php +++ b/lib/AdminActions/Util/Logger.php @@ -23,6 +23,8 @@ class Logger { protected static ?array $classes = null; public static function record(BaseAction $action): int { + global $AdminSession; + $packed = self::pack($action); $data = [ @@ -36,7 +38,7 @@ class Logger { ]; } else { $data += [ - 'admin_id' => admin_current_info()['id'], + 'admin_id' => $AdminSession->id, 'ip' => !empty($_SERVER['REMOTE_ADDR']) ? ip2ulong($_SERVER['REMOTE_ADDR']) : 0, ]; } diff --git a/lib/admin.php b/lib/admin.php index 2f9669c..dc34182 100644 --- a/lib/admin.php +++ b/lib/admin.php @@ -4,25 +4,31 @@ const ADMIN_SESSION_TIMEOUT = 86400 * 14; const ADMIN_COOKIE_NAME = 'admin_key'; const ADMIN_LOGIN_MAX_LENGTH = 32; -$AdminSession = [ - 'id' => null, - 'auth_id' => 0, - 'login' => null, -]; +$AdminSession = new class { + public function __construct( + public ?int $id = null, + public ?int $authId = null, + public ?string $csrfSalt = null, + public ?string $login = null, + ) {} + + public function mrProper(): void { + $this->id = null; + $this->authId = null; + $this->csrfSalt = null; + $this->login = null; + } + + public function makeCSRFSalt(string $salted_password): void { + $this->csrfSalt = salt_password(strrev($salted_password)); + } +}; function is_admin(): bool { global $AdminSession; - if ($AdminSession['id'] === null) + if ($AdminSession->id === null) _admin_check(); - return $AdminSession['id'] != 0; -} - -function admin_current_info(): array { - global $AdminSession; - return [ - 'id' => $AdminSession['id'], - 'login' => $AdminSession['login'] - ]; + return $AdminSession->id != 0; } function admin_exists(string $login): bool { @@ -63,7 +69,8 @@ function admin_auth(string $login, string $password): bool { global $AdminSession; $db = DB(); - $q = $db->query("SELECT id FROM admins WHERE login=? AND password=?", $login, salt_password($password)); + $salted_password = salt_password($password); + $q = $db->query("SELECT id FROM admins WHERE login=? AND password=?", $login, $salted_password); if (!$db->numRows($q)) return false; @@ -79,6 +86,7 @@ function admin_auth(string $login, string $password): bool { 'token' => $token, 'ts' => $time ]); + $auth_id = $db->insertId(); $db->insert('admin_log', [ 'admin_id' => $id, @@ -87,10 +95,10 @@ function admin_auth(string $login, string $password): bool { 'ua' => $_SERVER['HTTP_USER_AGENT'] ?? '', ]); - $AdminSession = [ - 'id' => $id, - 'login' => $login, - ]; + $AdminSession->id = $id; + $AdminSession->login = $login; + $AdminSession->makeCSRFSalt($salted_password); + $AdminSession->authId = $auth_id; _admin_set_cookie($token); return true; @@ -101,14 +109,11 @@ function admin_logout() { return; global $AdminSession; + $db = DB(); + $db->query("DELETE FROM admin_auth WHERE id=?", $AdminSession->authId); - $db->query("DELETE FROM admin_auth WHERE id=?", $AdminSession['auth_id']); - - $AdminSession['id'] = null; - $AdminSession['login'] = null; - $AdminSession['auth_id'] = 0; - + $AdminSession->mrProper(); _admin_unset_cookie(); } @@ -125,6 +130,7 @@ function _admin_check(): void { $q = $db->query("SELECT admin_auth.id AS auth_id, admin_auth.admin_id AS id, + admins.password AS salted_password, admins.login AS login FROM admin_auth LEFT JOIN admins ON admin_auth.admin_id=admins.id @@ -137,9 +143,10 @@ function _admin_check(): void { $info = $db->fetch($q); global $AdminSession; - $AdminSession['id'] = (int)$info['id']; - $AdminSession['login'] = $info['login']; - $AdminSession['auth_id'] = (int)$info['auth_id']; + $AdminSession->id = (int)$info['id']; + $AdminSession->login = $info['login']; + $AdminSession->authId = (int)$info['auth_id']; + $AdminSession->makeCSRFSalt($info['salted_password']); } function _admin_set_cookie(string $token): void { diff --git a/skin/admin.phps b/skin/admin.phps index 68d1f68..911f67f 100644 --- a/skin/admin.phps +++ b/skin/admin.phps @@ -49,10 +49,10 @@ return [$html, $js]; function index($ctx, $admin_login) { return << - Authorized as {$admin_login}
+ Authorized as {$admin_login} | Sign out
Uploads
- Sign out + HTML; }