From 492dee5e1aee0fbc2c5fb2d109a95beb0293adc4 Mon Sep 17 00:00:00 2001 From: djmaze Date: Wed, 10 Nov 2021 09:14:57 +0100 Subject: [PATCH] Improved openssl_encrypt support --- .../libraries/RainLoop/Actions/UserAuth.php | 4 +- .../libraries/RainLoop/Config/Application.php | 9 +++- .../0.0.0/app/libraries/snappymail/crypt.php | 44 ++++++++++++++++--- 3 files changed, 48 insertions(+), 9 deletions(-) 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 4a066560b..6c6df0b2b 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 @@ -234,9 +234,10 @@ trait UserAuth $this->ClearSignMeData(); $uuid = \SnappyMail\UUID::generate(); + \SnappyMail\Crypt::setCipher($this->Config()->Get('security', 'encrypt_cipher', '')); $data = \SnappyMail\Crypt::EncryptRaw($oAccount); - if ($data['xxtea']) { + if ('xxtea' === $data[0]) { static::SetSignMeTokenCookie(array( 'e' => $oAccount->Email(), 'u' => $uuid, @@ -272,6 +273,7 @@ trait UserAuth if (empty($sAuthToken)) { return null; } + \SnappyMail\Crypt::setCipher($this->Config()->Get('security', 'encrypt_cipher', '')); if (!empty($aTokenData['s'])) { $aAccountHash = \SnappyMail\Crypt::XxteaDecrypt($sAuthToken, \base64_decode($aTokenData['s'])); } else if (!empty($aTokenData['i'])) { diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Config/Application.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Config/Application.php index 544d9de1d..4d3c99a37 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Config/Application.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Config/Application.php @@ -115,6 +115,12 @@ class Application extends \RainLoop\Config\AbstractConfig } $upload_max_filesize = $upload_max_filesize / 1024 / 1024; + $sCipher = 'aes-256-cbc-hmac-sha1'; + $aCiphers = \SnappyMail\Crypt::listCiphers(); + if (!\in_array($sCipher, $aCiphers)) { + $sCipher = $aCiphers[\array_rand($aCiphers)]; + } + return array( 'webmail' => array( @@ -174,7 +180,8 @@ class Application extends \RainLoop\Config\AbstractConfig 'hide_x_mailer_header' => array(true), 'admin_panel_host' => array(''), 'admin_panel_key' => array('admin'), - 'content_security_policy' => array('') + 'content_security_policy' => array(''), + 'encrypt_cipher' => array($sCipher) ), 'ssl' => array( 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 7c5d66c1c..6565fe74a 100644 --- a/snappymail/v/0.0.0/app/libraries/snappymail/crypt.php +++ b/snappymail/v/0.0.0/app/libraries/snappymail/crypt.php @@ -7,7 +7,34 @@ abstract class Crypt /** * Or use 'aes-256-xts' ? */ - const CIPHER = 'aes-256-cbc-hmac-sha1'; + protected static $cipher = 'aes-256-cbc-hmac-sha1'; + + public static function listCiphers() : array + { + $list = array(); + if (\function_exists('openssl_get_cipher_methods')) { + $list = \openssl_get_cipher_methods(); + $list = \array_diff($list, \array_map('strtoupper',$list)); + $list = \array_filter($list, function($v){ + // DES/ECB/bf/rc insecure, GCM/CCM not supported + return !\preg_match('/(^(des|bf|rc))|-(ecb|gcm|ccm)/i', $v); + }); + \natcasesort($list); + } + return $list; + } + + public static function setCipher(string $cipher) : bool + { + if ($cipher) { + $aCiphers = static::listCiphers(); + if (\in_array($cipher, $aCiphers)) { + static::$cipher = $cipher; + return true; + } + } + return false; + } private static function Passphrase() : string { @@ -43,16 +70,16 @@ abstract class Crypt public static function EncryptRaw($data) : array { - if (\is_callable('openssl_encrypt')) { - $iv = \random_bytes(\openssl_cipher_iv_length(static::CIPHER)); + if (static::$cipher && \is_callable('openssl_encrypt')) { + $iv = \random_bytes(\openssl_cipher_iv_length(static::$cipher)); $data = \openssl_encrypt( \json_encode($data), - static::CIPHER, + static::$cipher, static::Passphrase(), OPENSSL_RAW_DATA, $iv ); - return [static::CIPHER, $iv, $data]; + return [static::$cipher, $iv, $data]; } $salt = \random_bytes(16); @@ -61,12 +88,15 @@ abstract class Crypt public static function OpenSSLDecrypt(string $data, string $iv) { - if (!$data || !$iv || !\is_callable('openssl_decrypt')) { + if (!$data || !$iv) { return null; } + if (!static::$cipher || !\is_callable('openssl_decrypt')) { + return static::XxteaDecrypt($data, $iv); + } return \json_decode(\openssl_decrypt( $data, - static::CIPHER, + static::$cipher, static::Passphrase(), OPENSSL_RAW_DATA, $iv