mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-08-28 19:49:20 +03:00
Improved FileStorage dedugging with expired session token fix
This commit is contained in:
parent
f2388bb936
commit
997dc87305
4 changed files with 46 additions and 39 deletions
|
|
@ -237,7 +237,7 @@ trait UserAuth
|
|||
* Server side control/kickout of logged in sessions
|
||||
* https://github.com/the-djmaze/snappymail/issues/151
|
||||
*/
|
||||
if (!isset($_COOKIE[Utils::SESSION_TOKEN])) {
|
||||
if (empty($_COOKIE[Utils::SESSION_TOKEN])) {
|
||||
// \MailSo\Base\Http::StatusHeader(401);
|
||||
$this->Logout(true);
|
||||
// $sAdditionalMessage = $this->StaticI18N('SESSION_UNDEFINED');
|
||||
|
|
@ -248,11 +248,19 @@ trait UserAuth
|
|||
$aData,
|
||||
$bThrowExceptionOnFalse
|
||||
);
|
||||
$sToken = Utils::GetSessionToken();
|
||||
if ($oMainAuthAccount && $this->StorageProvider()->Get($oMainAuthAccount, StorageType::SESSION, $sToken)) {
|
||||
$oMainAuthAccount || \SnappyMail\LOG::notice('TOKENS', 'AUTH_SPEC_TOKEN_KEY invalid');
|
||||
$sToken = $oMainAuthAccount ? Utils::GetSessionToken(false) : null;
|
||||
$sTokenValue = $sToken ? $this->StorageProvider()->Get($oMainAuthAccount, StorageType::SESSION, $sToken) : null;
|
||||
if ($oMainAuthAccount && $sTokenValue) {
|
||||
$this->oMainAuthAccount = $oMainAuthAccount;
|
||||
} else {
|
||||
$oMainAuthAccount && $this->StorageProvider()->Clear($oMainAuthAccount, StorageType::SESSION, $sToken);
|
||||
if ($oMainAuthAccount) {
|
||||
$sToken || \SnappyMail\LOG::notice('TOKENS', 'SESSION_TOKEN not found');
|
||||
if ($sToken) {
|
||||
$oMainAuthAccount && $this->StorageProvider()->Clear($oMainAuthAccount, StorageType::SESSION, $sToken);
|
||||
$sTokenValue || \SnappyMail\LOG::notice('TOKENS', 'SESSION_TOKEN value invalid: ' . \gettype($sTokenValue));
|
||||
}
|
||||
}
|
||||
Utils::ClearCookie(Utils::SESSION_TOKEN);
|
||||
// \MailSo\Base\Http::StatusHeader(401);
|
||||
$this->Logout(true);
|
||||
|
|
@ -266,10 +274,7 @@ trait UserAuth
|
|||
}
|
||||
}
|
||||
|
||||
if ($this->oMainAuthAccount) {
|
||||
// Extend session cookie lifetime
|
||||
$this->StorageProvider()->Put($this->oMainAuthAccount, StorageType::SESSION, Utils::GetSessionToken(), 'true');
|
||||
} else if ($bThrowExceptionOnFalse) {
|
||||
if ($bThrowExceptionOnFalse && !$this->oMainAuthAccount) {
|
||||
throw new ClientException(Notifications::InvalidToken, null, 'Account undefined');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,13 +19,9 @@ class Storage extends \RainLoop\Providers\AbstractProvider
|
|||
*/
|
||||
private function verifyAccount($mAccount, int $iStorageType) : bool
|
||||
{
|
||||
if (\RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY !== $iStorageType &&
|
||||
!($mAccount instanceof \RainLoop\Model\Account || \is_string($mAccount)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return \RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY === $iStorageType
|
||||
|| $mAccount instanceof \RainLoop\Model\Account
|
||||
|| \is_string($mAccount);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -34,12 +30,9 @@ class Storage extends \RainLoop\Providers\AbstractProvider
|
|||
*/
|
||||
public function Put($mAccount, int $iStorageType, string $sKey, string $sValue) : bool
|
||||
{
|
||||
if (!$this->verifyAccount($mAccount, $iStorageType))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->oDriver->Put($mAccount, $iStorageType, $sKey, $sValue);
|
||||
return $this->verifyAccount($mAccount, $iStorageType)
|
||||
? $this->oDriver->Put($mAccount, $iStorageType, $sKey, $sValue)
|
||||
: false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -50,12 +43,9 @@ class Storage extends \RainLoop\Providers\AbstractProvider
|
|||
*/
|
||||
public function Get($mAccount, int $iStorageType, string $sKey, $mDefault = false)
|
||||
{
|
||||
if (!$this->verifyAccount($mAccount, $iStorageType))
|
||||
{
|
||||
return $mDefault;
|
||||
}
|
||||
|
||||
return $this->oDriver->Get($mAccount, $iStorageType, $sKey, $mDefault);
|
||||
return $this->verifyAccount($mAccount, $iStorageType)
|
||||
? $this->oDriver->Get($mAccount, $iStorageType, $sKey, $mDefault)
|
||||
: $mDefault;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -63,12 +53,9 @@ class Storage extends \RainLoop\Providers\AbstractProvider
|
|||
*/
|
||||
public function Clear($mAccount, int $iStorageType, string $sKey) : bool
|
||||
{
|
||||
if (!$this->verifyAccount($mAccount, $iStorageType))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->oDriver->Clear($mAccount, $iStorageType, $sKey);
|
||||
return $this->verifyAccount($mAccount, $iStorageType)
|
||||
? $this->oDriver->Clear($mAccount, $iStorageType, $sKey)
|
||||
: false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ class FileStorage implements \RainLoop\Providers\Storage\IStorage
|
|||
$sFileName && \RainLoop\Utils::saveFile($sFileName, $sValue);
|
||||
return true;
|
||||
} catch (\Throwable $e) {
|
||||
\error_log("{$e->getMessage()}: {$sFileName}");
|
||||
\SnappyMail\LOG::warning('FileStorage', $e->getMessage());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
@ -55,6 +55,10 @@ class FileStorage implements \RainLoop\Providers\Storage\IStorage
|
|||
$sFileName = $this->generateFileName($mAccount, $iStorageType, $sKey);
|
||||
if ($sFileName && \file_exists($sFileName)) {
|
||||
$mValue = \file_get_contents($sFileName);
|
||||
// Update mtime to prevent garbage collection
|
||||
if (StorageType::SESSION === $iStorageType) {
|
||||
\touch($sFileName);
|
||||
}
|
||||
}
|
||||
return false === $mValue ? $mDefault : $mValue;
|
||||
}
|
||||
|
|
@ -154,6 +158,7 @@ class FileStorage implements \RainLoop\Providers\Storage\IStorage
|
|||
|
||||
public function GC() : void
|
||||
{
|
||||
\clearstatcache();
|
||||
foreach (\glob("{$this->sDataPath}/*", GLOB_ONLYDIR) as $sDomain) {
|
||||
foreach (\glob("{$sDomain}/*", GLOB_ONLYDIR) as $sLocal) {
|
||||
\MailSo\Base\Utils::RecTimeDirRemove("{$sLocal}/.sign_me", 3600 * 24 * 30); // 30 days
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ class Utils
|
|||
{
|
||||
return \SnappyMail\Crypt::DecryptUrlSafe(
|
||||
$sEncodedValues,
|
||||
\sha1(APP_SALT.$sCustomKey.'Q'.static::GetSessionToken())
|
||||
\sha1(APP_SALT.$sCustomKey.'Q'.static::GetSessionToken(false))
|
||||
) ?: null;
|
||||
}
|
||||
|
||||
|
|
@ -72,14 +72,17 @@ class Utils
|
|||
}
|
||||
}
|
||||
|
||||
public static function GetSessionToken() : string
|
||||
public static function GetSessionToken(bool $generate = true) : ?string
|
||||
{
|
||||
$sToken = static::GetCookie(self::SESSION_TOKEN, null);
|
||||
if (!$sToken) {
|
||||
if (!$generate) {
|
||||
return null;
|
||||
}
|
||||
\SnappyMail\LOG::debug('TOKENS', 'New SESSION_TOKEN');
|
||||
$sToken = \MailSo\Base\Utils::Sha1Rand(APP_SALT);
|
||||
static::SetCookie(self::SESSION_TOKEN, $sToken);
|
||||
}
|
||||
|
||||
return \sha1('Session'.APP_SALT.$sToken.'Token'.APP_SALT);
|
||||
}
|
||||
|
||||
|
|
@ -225,11 +228,18 @@ class Utils
|
|||
{
|
||||
$dir = \dirname($filename);
|
||||
if (!\is_dir($dir) && !\mkdir($dir, 0700, true)) {
|
||||
throw new \RainLoop\Exceptions\Exception('Failed to create directory "'.$dir.'"');
|
||||
throw new Exceptions\Exception('Failed to create directory "'.$dir.'"');
|
||||
}
|
||||
if (false === \file_put_contents($filename, $data)) {
|
||||
throw new \RainLoop\Exceptions\Exception('Failed to save file "'.$filename.'"');
|
||||
throw new Exceptions\Exception('Failed to save file "'.$filename.'"');
|
||||
}
|
||||
\clearstatcache();
|
||||
\chmod($filename, 0600);
|
||||
/*
|
||||
try {
|
||||
} catch (\Throwable $oException) {
|
||||
throw new Exceptions\Exception($oException->getMessage() . ': ' . \error_get_last()['message']);
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue