Improved FileStorage dedugging with expired session token fix

This commit is contained in:
djmaze 2021-12-28 10:44:56 +01:00
parent f2388bb936
commit 997dc87305
4 changed files with 46 additions and 39 deletions

View file

@ -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');
}
}

View file

@ -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;
}
/**

View file

@ -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

View file

@ -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']);
}
*/
}
}