diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Contacts.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Contacts.php index 20865b619..663f15c52 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Contacts.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Contacts.php @@ -22,14 +22,17 @@ trait Contacts $mData = $this->getContactsSyncData($oAccount); - $bResult = $this->StorageProvider()->Put($oAccount, + $sPassword = APP_DUMMY === $sPassword && isset($mData['Password']) + ? $mData['Password'] : (APP_DUMMY === $sPassword ? '' : $sPassword); + + $bResult = $this->StorageProvider()->Put( + $oAccount, \RainLoop\Providers\Storage\Enumerations\StorageType::CONFIG, 'contacts_sync', - \RainLoop\Utils::EncodeKeyValues(array( + \json_encode(array( 'Enable' => $bEnabled, 'User' => $sUser, - 'Password' => APP_DUMMY === $sPassword && isset($mData['Password']) ? - $mData['Password'] : (APP_DUMMY === $sPassword ? '' : $sPassword), + 'Password' => $sPassword ? \SnappyMail\Crypt::Encrypt($sPassword, $oAccount->Password() ?: APP_SALT) : null, 'Url' => $sUrl )) ); @@ -240,15 +243,25 @@ trait Contacts protected function getContactsSyncData(\RainLoop\Model\Account $oAccount) : ?array { - $mResult = null; $sData = $this->StorageProvider()->Get($oAccount, \RainLoop\Providers\Storage\Enumerations\StorageType::CONFIG, 'contacts_sync' ); if (!empty($sData)) { + $aData = \json_decode($sData); + if ($aData) { + if ($aData['Password']) { + $aData['Password'] = \SnappyMail\Crypt::DecryptFromJSON( + $aData['Password'], + $oAccount->Password() ?: APP_SALT + ); + } + return $aData; + } + $aData = \RainLoop\Utils::DecodeKeyValues($sData); if ($aData) { - $mResult = array( + return array( 'Enable' => isset($aData['Enable']) ? !!$aData['Enable'] : false, 'Url' => isset($aData['Url']) ? \trim($aData['Url']) : '', 'User' => isset($aData['User']) ? \trim($aData['User']) : '', @@ -256,7 +269,7 @@ trait Contacts ); } } - return $mResult; + return null; } public function RawContactsVcf() : bool diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/UserAuth.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/UserAuth.php index c94b67599..f7e046256 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/UserAuth.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/UserAuth.php @@ -178,8 +178,10 @@ trait UserAuth } } - $aData = \json_decode(\MailSo\Base\Utils::UrlSafeBase64Decode($this->sSpecAuthToken), true); - $aData = \is_array($aData) ? \SnappyMail\Crypt::Decrypt(\array_map('base64_decode', $aData)) : null; + $aData = \SnappyMail\Crypt::DecryptFromJSON( + \MailSo\Base\Utils::UrlSafeBase64Decode($this->sSpecAuthToken), + APP_SALT . Utils::GetShortToken() + ); if (!empty($aData)) { $this->oSpecAuthAccount = Account::NewInstanceFromTokenArray( $this, @@ -198,13 +200,10 @@ trait UserAuth public function SetAuthToken(Account $oAccount): void { - $sSpecAuthToken = \MailSo\Base\Utils::UrlSafeBase64Encode(\json_encode(\array_map( - 'base64_encode', - \SnappyMail\Crypt::Encrypt( - $oAccount, - APP_SALT . Utils::GetShortToken() - ) - ))); + $sSpecAuthToken = \MailSo\Base\Utils::UrlSafeBase64Encode(\SnappyMail\Crypt::EncryptToJSON( + $oAccount, + APP_SALT . Utils::GetShortToken() + )); $this->sSpecAuthToken = $sSpecAuthToken; $this->oSpecAuthAccount = null; diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Api.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Api.php index eda6b492a..e40f9c7a1 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Api.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Api.php @@ -165,16 +165,14 @@ class Api { $sSsoHash = \MailSo\Base\Utils::Sha1Rand(\sha1($sPassword.$sEmail)); - $data = \SnappyMail\Crypt::Encrypt(array( - 'Email' => $sEmail, - 'Password' => $sPassword, - 'AdditionalOptions' => $aAdditionalOptions, - 'Time' => $bUseTimeout ? \time() : 0 - ), $sSsoHash); - return static::Actions()->Cacher()->Set( KeyPathHelper::SsoCacherKey($sSsoHash), - \json_encode(\array_map('base64_encode', $data)) + \SnappyMail\Crypt::EncryptToJSON(array( + 'Email' => $sEmail, + 'Password' => $sPassword, + 'AdditionalOptions' => $aAdditionalOptions, + 'Time' => $bUseTimeout ? \time() : 0 + ), $sSsoHash) ) ? $sSsoHash : null; } diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Model/Account.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Model/Account.php index 8c2c2f764..5c104305a 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Model/Account.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Model/Account.php @@ -172,6 +172,14 @@ class Account implements \JsonSerializable public function GetAuthToken() : string { return Utils::EncodeKeyValues($this->jsonSerialize()); +/* + return \MailSo\Base\Utils::UrlSafeBase64Encode( + \MailSo\Base\Crypt::Encrypt( + \json_encode($this), + \md5(APP_SALT.$sCustomKey) + ) + ); +*/ } public static function NewInstanceByLogin(\RainLoop\Actions $oActions, string $sEmail, string $sLogin, string $sPassword, string $sClientCert = '', bool $bThrowException = false): ?self diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/ServiceActions.php b/snappymail/v/0.0.0/app/libraries/RainLoop/ServiceActions.php index 31f47efb6..97802fc15 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/ServiceActions.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/ServiceActions.php @@ -671,8 +671,7 @@ class ServiceActions $sSsoSubData = $this->Cacher()->Get(KeyPathHelper::SsoCacherKey($sSsoHash)); if (!empty($sSsoSubData)) { - $aData = \json_decode($sSsoSubData, true); - $aData = \is_array($aData) ? \SnappyMail\Crypt::Decrypt(\array_map('base64_decode', $aData), $sSsoHash) : null; + $aData = \SnappyMail\Crypt::DecryptFromJSON($sSsoSubData, $sSsoHash); $this->Cacher()->Delete(KeyPathHelper::SsoCacherKey($sSsoHash)); diff --git a/snappymail/v/0.0.0/app/libraries/snappymail/crypt.php b/snappymail/v/0.0.0/app/libraries/snappymail/crypt.php index ed75cab59..0a62f60f7 100644 --- a/snappymail/v/0.0.0/app/libraries/snappymail/crypt.php +++ b/snappymail/v/0.0.0/app/libraries/snappymail/crypt.php @@ -85,6 +85,12 @@ abstract class Crypt } } + public static function DecryptFromJSON(string $data, string $key = null) /* : mixed */ + { + $aData = \json_decode($data, true); + $aData = \is_array($aData) ? static::Decrypt(\array_map('base64_decode', $aData), $key) : null; + } + public static function Encrypt($data, string $key = null) : array { if (\is_callable('sodium_crypto_aead_xchacha20poly1305_ietf_encrypt')) { @@ -101,6 +107,11 @@ abstract class Crypt return ['xxtea', $salt, static::XxteaEncrypt($data, $salt)]; } + public static function EncryptToJSON($data, string $key = null) : string + { + return \json_encode(\array_map('base64_encode', static::Encrypt($data, $key))); + } + public static function SodiumDecrypt(string $data, string $nonce, string $key = null) /* : mixed */ { if (!\is_callable('sodium_crypto_aead_xchacha20poly1305_ietf_decrypt')) {