jenkins-bot has submitted this change and it was merged.

Change subject: Fix encryption code in Session
......................................................................


Fix encryption code in Session

* verify that the algorithm that's about to be used is available
* fix exception namespace

Bug: T136587
Change-Id: I9f8636bef0e10b4f2b8bfe232a26a8c33376ca04
(cherry picked from commit c331a1ae08a98fc6300dce8d407d369db271256f)
---
M includes/session/Session.php
1 file changed, 82 insertions(+), 57 deletions(-)

Approvals:
  Gergő Tisza: Looks good to me, approved
  jenkins-bot: Verified



diff --git a/includes/session/Session.php b/includes/session/Session.php
index 29878d4..2621238 100644
--- a/includes/session/Session.php
+++ b/includes/session/Session.php
@@ -401,6 +401,38 @@
        }
 
        /**
+        * Decide what type of encryption to use, based on system capabilities.
+        * @return array
+        */
+       private function getEncryptionAlgorithm() {
+               global $wgSessionInsecureSecrets;
+
+               if (
+                       function_exists( 'openssl_encrypt' )
+                       && in_array( 'aes-256-ctr', 
openssl_get_cipher_methods(), true )
+               ) {
+                       return [ 'openssl', 'aes-256-ctr' ];
+               } elseif (
+                       function_exists( 'mcrypt_encrypt' )
+                       && in_array( 'rijndael-128', mcrypt_list_algorithms(), 
true )
+                       && in_array( 'ctr', mcrypt_list_modes(), true )
+               ) {
+                       return [ 'mcrypt', 'rijndael-128', 'ctr' ];
+               } elseif ( $wgSessionInsecureSecrets ) {
+                       // @todo: import a pure-PHP library for AES instead of 
this
+                       return [ 'insecure' ];
+               } else {
+                       throw new \BadMethodCallException(
+                               'Encryption is not available. You really should 
install the PHP OpenSSL extension, ' .
+                               'or failing that the mcrypt extension. But if 
you really can\'t and you\'re willing ' .
+                               'to accept insecure storage of sensitive 
session data, set ' .
+                               '$wgSessionInsecureSecrets = true in 
LocalSettings.php to make this exception go away.'
+                       );
+               }
+
+       }
+
+       /**
         * Set a value in the session, encrypted
         *
         * This relies on the secrecy of $wgSecretKey (by default), or 
$wgSessionSecret.
@@ -409,8 +441,6 @@
         * @param mixed $value
         */
        public function setSecret( $key, $value ) {
-               global $wgSessionInsecureSecrets;
-
                list( $encKey, $hmacKey ) = $this->getSecretKeys();
                $serialized = serialize( $value );
 
@@ -420,27 +450,27 @@
                // Encrypt
                // @todo: import a pure-PHP library for AES instead of doing 
$wgSessionInsecureSecrets
                $iv = \MWCryptRand::generate( 16, true );
-               if ( function_exists( 'openssl_encrypt' ) ) {
-                       $ciphertext = openssl_encrypt( $serialized, 
'aes-256-ctr', $encKey, OPENSSL_RAW_DATA, $iv );
-                       if ( $ciphertext === false ) {
-                               throw new UnexpectedValueException( 'Encryption 
failed: ' . openssl_error_string() );
-                       }
-               } elseif ( function_exists( 'mcrypt_encrypt' ) ) {
-                       $ciphertext = mcrypt_encrypt( 'rijndael-128', $encKey, 
$serialized, 'ctr', $iv );
-                       if ( $ciphertext === false ) {
-                               throw new UnexpectedValueException( 'Encryption 
failed' );
-                       }
-               } elseif ( $wgSessionInsecureSecrets ) {
-                       $ex = new \Exception( 'No encryption is available, 
storing data as plain text' );
-                       $this->logger->warning( $ex->getMessage(), [ 
'exception' => $ex ] );
-                       $ciphertext = $serialized;
-               } else {
-                       throw new \BadMethodCallException(
-                               'Encryption is not available. You really should 
install the PHP OpenSSL extension, ' .
-                               'or failing that the mcrypt extension. But if 
you really can\'t and you\'re willing ' .
-                               'to accept insecure storage of sensitive 
session data, set ' .
-                               '$wgSessionInsecureSecrets = true in 
LocalSettings.php to make this exception go away.'
-                       );
+               $algorithm = $this->getEncryptionAlgorithm();
+               switch ( $algorithm[0] ) {
+                       case 'openssl':
+                               $ciphertext = openssl_encrypt( $serialized, 
$algorithm[1], $encKey, OPENSSL_RAW_DATA, $iv );
+                               if ( $ciphertext === false ) {
+                                       throw new \UnexpectedValueException( 
'Encryption failed: ' . openssl_error_string() );
+                               }
+                               break;
+                       case 'mcrypt':
+                               $ciphertext = mcrypt_encrypt( $algorithm[1], 
$encKey, $serialized, $algorithm[2], $iv );
+                               if ( $ciphertext === false ) {
+                                       throw new \UnexpectedValueException( 
'Encryption failed' );
+                               }
+                               break;
+                       case 'insecure':
+                               $ex = new \Exception( 'No encryption is 
available, storing data as plain text' );
+                               $this->logger->warning( $ex->getMessage(), [ 
'exception' => $ex ] );
+                               $ciphertext = $serialized;
+                               break;
+                       default:
+                               throw new \LogicException( 'invalid algorithm' 
);
                }
 
                // Seal
@@ -459,8 +489,6 @@
         * @return mixed
         */
        public function getSecret( $key, $default = null ) {
-               global $wgSessionInsecureSecrets;
-
                // Fetch
                $encrypted = $this->get( $key, null );
                if ( $encrypted === null ) {
@@ -488,38 +516,35 @@
                }
 
                // Decrypt
-               // @todo: import a pure-PHP library for AES instead of doing 
$wgSessionInsecureSecrets
-               if ( function_exists( 'openssl_decrypt' ) ) {
-                       $serialized = openssl_decrypt(
-                               base64_decode( $ciphertext ), 'aes-256-ctr', 
$encKey, OPENSSL_RAW_DATA, base64_decode( $iv )
-                       );
-                       if ( $serialized === false ) {
-                               $ex = new \Exception( 'Decyption failed: ' . 
openssl_error_string() );
-                               $this->logger->debug( $ex->getMessage(), [ 
'exception' => $ex ] );
-                               return $default;
-                       }
-               } elseif ( function_exists( 'mcrypt_decrypt' ) ) {
-                       $serialized = mcrypt_decrypt(
-                               'rijndael-128', $encKey, base64_decode( 
$ciphertext ), 'ctr', base64_decode( $iv )
-                       );
-                       if ( $serialized === false ) {
-                               $ex = new \Exception( 'Decyption failed' );
-                               $this->logger->debug( $ex->getMessage(), [ 
'exception' => $ex ] );
-                               return $default;
-                       }
-               } elseif ( $wgSessionInsecureSecrets ) {
-                       $ex = new \Exception(
-                               'No encryption is available, retrieving data 
that was stored as plain text'
-                       );
-                       $this->logger->warning( $ex->getMessage(), [ 
'exception' => $ex ] );
-                       $serialized = base64_decode( $ciphertext );
-               } else {
-                       throw new \BadMethodCallException(
-                               'Encryption is not available. You really should 
install the PHP OpenSSL extension, ' .
-                               'or failing that the mcrypt extension. But if 
you really can\'t and you\'re willing ' .
-                               'to accept insecure storage of sensitive 
session data, set ' .
-                               '$wgSessionInsecureSecrets = true in 
LocalSettings.php to make this exception go away.'
-                       );
+               $algorithm = $this->getEncryptionAlgorithm();
+               switch ( $algorithm[0] ) {
+                       case 'openssl':
+                               $serialized = openssl_decrypt( base64_decode( 
$ciphertext ), $algorithm[1], $encKey,
+                                       OPENSSL_RAW_DATA, base64_decode( $iv ) 
);
+                               if ( $serialized === false ) {
+                                       $ex = new \Exception( 'Decyption 
failed: ' . openssl_error_string() );
+                                       $this->logger->debug( 
$ex->getMessage(), [ 'exception' => $ex ] );
+                                       return $default;
+                               }
+                               break;
+                       case 'mcrypt':
+                               $serialized = mcrypt_decrypt( $algorithm[1], 
$encKey, base64_decode( $ciphertext ),
+                                       $algorithm[2], base64_decode( $iv ) );
+                               if ( $serialized === false ) {
+                                       $ex = new \Exception( 'Decyption 
failed' );
+                                       $this->logger->debug( 
$ex->getMessage(), [ 'exception' => $ex ] );
+                                       return $default;
+                               }
+                               break;
+                       case 'insecure':
+                               $ex = new \Exception(
+                                       'No encryption is available, retrieving 
data that was stored as plain text'
+                               );
+                               $this->logger->warning( $ex->getMessage(), [ 
'exception' => $ex ] );
+                               $serialized = base64_decode( $ciphertext );
+                               break;
+                       default:
+                               throw new \LogicException( 'invalid algorithm' 
);
                }
 
                $value = unserialize( $serialized );

-- 
To view, visit https://gerrit.wikimedia.org/r/296534
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: I9f8636bef0e10b4f2b8bfe232a26a8c33376ca04
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/core
Gerrit-Branch: REL1_27
Gerrit-Owner: Gergő Tisza <gti...@wikimedia.org>
Gerrit-Reviewer: Anomie <bjor...@wikimedia.org>
Gerrit-Reviewer: Gergő Tisza <gti...@wikimedia.org>
Gerrit-Reviewer: jenkins-bot <>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to