admin: csrf refactoring
This commit is contained in:
parent
96236f66d3
commit
8938276d64
@ -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');
|
||||
}
|
@ -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() {
|
||||
|
@ -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,
|
||||
];
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -49,10 +49,10 @@ return [$html, $js];
|
||||
function index($ctx, $admin_login) {
|
||||
return <<<HTML
|
||||
<div class="admin-page">
|
||||
Authorized as <b>{$admin_login}</b><br>
|
||||
Authorized as <b>{$admin_login}</b> | <a href="/admin/logout/?token={$ctx->csrf('logout')}">Sign out</a><br>
|
||||
<!--<a href="/admin/log/">Log</a><br/>-->
|
||||
<a href="/admin/uploads/">Uploads</a><br>
|
||||
<a href="/admin/logout/?token={$ctx->csrf('logout')}">Sign out</a>
|
||||
|
||||
</div>
|
||||
HTML;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user