Store persistent-login keys as SHA-256 hashes.
Each device now has its own row. Editors must log in again once after deploying.
This commit is contained in:
+35
-23
@@ -25,38 +25,48 @@ if (isset($_SERVER['HTTPS'])) {
|
|||||||
header( 'Pragma: no-cache' );
|
header( 'Pragma: no-cache' );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Persistent logins: the cookie holds "username|key", and the database
|
||||||
|
* holds only a SHA-256 of the key, so a copy of the table cannot be used
|
||||||
|
* to log in. Each device has its own row.
|
||||||
|
*/
|
||||||
|
function persistent_cookie() {
|
||||||
|
$cookie_data = $_COOKIE['PersistentAuth'] ?? '';
|
||||||
|
if (!is_string($cookie_data))
|
||||||
|
$cookie_data = '';
|
||||||
|
return explode("|", $cookie_data, 2) + array('', '');
|
||||||
|
}
|
||||||
|
|
||||||
|
function persistent_key_hash($key) {
|
||||||
|
return hash('sha256', $key);
|
||||||
|
}
|
||||||
|
|
||||||
function check_persistent_login() {
|
function check_persistent_login() {
|
||||||
if (!array_key_exists('PersistentAuth', $_COOKIE)) {
|
if (!array_key_exists('PersistentAuth', $_COOKIE)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
global $db, $is_admin;
|
global $db, $is_admin;
|
||||||
$table = "persistent_sessions";
|
$table = "persistent_sessions";
|
||||||
|
list($username, $key) = persistent_cookie();
|
||||||
|
if ($username === '' || $key === '')
|
||||||
|
return false;
|
||||||
|
$key_hash = persistent_key_hash($key);
|
||||||
|
|
||||||
open_db('open');
|
open_db('open');
|
||||||
|
$query = "SELECT * FROM $table WHERE username = ? AND session = ? LIMIT 1";
|
||||||
$cookie_data = (string)$_COOKIE['PersistentAuth'];
|
$getid = $db->execute_query($query, array($username, $key_hash)) or die("Query failed: ".$db->error);
|
||||||
list($username, $key) = explode("|", $cookie_data, 2) + array('', '');
|
|
||||||
|
|
||||||
$query = "SELECT * FROM $table WHERE username = ? LIMIT 1";
|
|
||||||
$getid = $db->execute_query($query, array($username)) or die("Query failed: ".$db->error);
|
|
||||||
$row = $getid->fetch_assoc();
|
$row = $getid->fetch_assoc();
|
||||||
open_db('close');
|
open_db('close');
|
||||||
|
|
||||||
if (isset($row)) {
|
if (isset($row) && hash_equals((string)$row['session'], $key_hash)) {
|
||||||
// Set up session, and delete old cookie, and create new persistent cookie
|
// Log in, then swap the used key for a new one
|
||||||
$stored_session = $row['session'];
|
|
||||||
if ($stored_session == $key) {
|
|
||||||
// login
|
|
||||||
login_editor($username);
|
login_editor($username);
|
||||||
// delete cookie
|
|
||||||
delete_persistent_login();
|
delete_persistent_login();
|
||||||
// create new cookie
|
|
||||||
create_persistent_login($username);
|
create_persistent_login($username);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function create_persistent_login($username) {
|
function create_persistent_login($username) {
|
||||||
$validity = strtotime('+1 year'); // Time to keep the session valid
|
$validity = strtotime('+1 year'); // Time to keep the session valid
|
||||||
@@ -64,11 +74,11 @@ function create_persistent_login($username) {
|
|||||||
$table = "persistent_sessions";
|
$table = "persistent_sessions";
|
||||||
open_db('open');
|
open_db('open');
|
||||||
|
|
||||||
$key = bin2hex(random_bytes(100));
|
$key = bin2hex(random_bytes(32));
|
||||||
|
|
||||||
// Add session key to database
|
// Add the hash of the session key to the database
|
||||||
$query = "INSERT INTO $table (username, session) VALUES (?, ?)";
|
$query = "INSERT INTO $table (username, session) VALUES (?, ?)";
|
||||||
$db->execute_query($query, array($username, $key)) or die("Query failed: ".$db->error);
|
$db->execute_query($query, array($username, persistent_key_hash($key))) or die("Query failed: ".$db->error);
|
||||||
open_db('close');
|
open_db('close');
|
||||||
|
|
||||||
// Create cookie with key
|
// Create cookie with key
|
||||||
@@ -82,16 +92,18 @@ function delete_persistent_login() {
|
|||||||
$table = "persistent_sessions";
|
$table = "persistent_sessions";
|
||||||
open_db('open');
|
open_db('open');
|
||||||
|
|
||||||
$cookie_data = (string)($_COOKIE['PersistentAuth'] ?? '');
|
list($username, $key) = persistent_cookie();
|
||||||
list($username, $key) = explode("|", $cookie_data, 2) + array('', '');
|
|
||||||
|
|
||||||
// Remove this session key from the database
|
// Remove this session key from the database
|
||||||
|
if ($username !== '' && $key !== '') {
|
||||||
$query = "DELETE FROM $table WHERE username = ? AND session = ?";
|
$query = "DELETE FROM $table WHERE username = ? AND session = ?";
|
||||||
$db->execute_query($query, array($username, $key)) or die("Query failed: ".$db->error);
|
$db->execute_query($query, array($username, persistent_key_hash($key))) or die("Query failed: ".$db->error);
|
||||||
|
}
|
||||||
|
|
||||||
// Reap old sessions
|
// Reap old sessions, and keys stored before they were hashed
|
||||||
$query = "DELETE FROM $table " .
|
$query = "DELETE FROM $table " .
|
||||||
" WHERE created < DATE_SUB(now(), INTERVAL 1 YEAR);";
|
" WHERE created < DATE_SUB(now(), INTERVAL 1 YEAR)" .
|
||||||
|
" OR CHAR_LENGTH(session) <> 64;";
|
||||||
$db->query($query) or die("Query failed: ".$db->error);
|
$db->query($query) or die("Query failed: ".$db->error);
|
||||||
|
|
||||||
open_db('close');
|
open_db('close');
|
||||||
|
|||||||
Reference in New Issue
Block a user