Enhance security and functionality of Bludit Secure plugin
- Added userHandle support in secure.js for WebAuthn credential response. - Implemented authorization check for SSO configuration changes in plugin.php. - Improved user session management and validation in App.php, including userStamp for enhanced security. - Updated Store.php to ensure secure data handling and improved error handling during transactions. - Removed outdated test files for auto-passkey and core functionality. - Added OidcClient.php to enforce strict validation of OpenID Connect requests and responses. - Enhanced error handling and logging throughout the application for better debugging.
This commit is contained in:
1 parent
0b983bcfbb
commit
1742084b45
12 files changed
+192
-228
No files matched your search
+23
-8
@@ -11,25 +11,38 @@ final class Store
|
||||
}
|
||||
public function transaction(callable $fn): mixed {
|
||||
$lock = fopen($this->dir.'/secure.lock.php', 'c+');
|
||||
if (!$lock || !flock($lock, LOCK_EX)) { throw new \RuntimeException('Storage locked'); }
|
||||
if (!$lock) { throw new \RuntimeException('Storage locked'); }
|
||||
if (!flock($lock, LOCK_EX)) { fclose($lock); throw new \RuntimeException('Storage locked'); }
|
||||
$key = null;
|
||||
try {
|
||||
chmod($this->dir.'/secure.lock.php', 0600);
|
||||
$kp = $this->dir.'/secure.key.php';
|
||||
$path = $this->dir.'/secure.data.php';
|
||||
$prefix = "<?php exit; ?>\n";
|
||||
if (!file_exists($kp)) {
|
||||
if (file_exists($this->dir.'/secure.data.php')) { throw new \RuntimeException('Missing encryption key'); }
|
||||
$this->write($kp, $prefix.base64_encode(random_bytes(SODIUM_CRYPTO_SECRETBOX_KEYBYTES)));
|
||||
if (file_exists($path)) { throw new \RuntimeException('Missing encryption key'); }
|
||||
$initialKey = random_bytes(SODIUM_CRYPTO_SECRETBOX_KEYBYTES);
|
||||
try {
|
||||
$this->write($kp, $prefix.base64_encode($initialKey));
|
||||
$nonce = random_bytes(24);
|
||||
$this->write($path, $prefix.base64_encode($nonce.sodium_crypto_secretbox('{"accounts":[],"limits":[]}', $nonce, $initialKey)));
|
||||
} finally { sodium_memzero($initialKey); }
|
||||
}
|
||||
$key = base64_decode(substr(file_get_contents($kp), strlen($prefix)), true);
|
||||
if (!file_exists($path)) { throw new \RuntimeException('Missing security data'); }
|
||||
$keyFile = file_get_contents($kp);
|
||||
if ($keyFile === false || !str_starts_with($keyFile, $prefix)) { throw new \RuntimeException('Invalid encryption key header'); }
|
||||
$key = base64_decode(substr($keyFile, strlen($prefix)), true);
|
||||
if ($key === false || strlen($key) !== SODIUM_CRYPTO_SECRETBOX_KEYBYTES) { throw new \RuntimeException('Invalid encryption key'); }
|
||||
$path = $this->dir.'/secure.data.php';
|
||||
$data = ['accounts'=>[], 'limits'=>[]];
|
||||
if (file_exists($path)) {
|
||||
$raw = base64_decode(substr(file_get_contents($path), strlen($prefix)), true);
|
||||
$dataFile = file_get_contents($path);
|
||||
if ($dataFile === false || !str_starts_with($dataFile, $prefix)) { throw new \RuntimeException('Invalid storage header'); }
|
||||
$raw = base64_decode(substr($dataFile, strlen($prefix)), true);
|
||||
if ($raw === false || strlen($raw) < 40) { throw new \RuntimeException('Invalid storage'); }
|
||||
$plain = sodium_crypto_secretbox_open(substr($raw, 24), substr($raw, 0, 24), $key);
|
||||
if ($plain === false) { throw new \RuntimeException('Storage authentication failed'); }
|
||||
$data = json_decode($plain, true, 64, JSON_THROW_ON_ERROR);
|
||||
if (!is_array($data) || !isset($data['accounts'], $data['limits']) || !is_array($data['accounts']) || !is_array($data['limits'])) { throw new \RuntimeException('Invalid storage structure'); }
|
||||
}
|
||||
$before = $data;
|
||||
$result = $fn($data);
|
||||
@@ -37,9 +50,11 @@ final class Store
|
||||
$nonce = random_bytes(24);
|
||||
$this->write($path, $prefix.base64_encode($nonce.sodium_crypto_secretbox(json_encode($data, JSON_THROW_ON_ERROR), $nonce, $key)));
|
||||
}
|
||||
sodium_memzero($key);
|
||||
return $result;
|
||||
} finally { flock($lock, LOCK_UN); fclose($lock); }
|
||||
} finally {
|
||||
if (is_string($key)) { sodium_memzero($key); }
|
||||
flock($lock, LOCK_UN); fclose($lock);
|
||||
}
|
||||
}
|
||||
private function write(string $path, string $data): void {
|
||||
$tmp = tempnam($this->dir, '.secure-');
|
||||
|
||||
Reference in new issue
Block a user