Index: branches/5.2.x/composer.json
===================================================================
diff -u -N -r16637 -r16691
--- branches/5.2.x/composer.json (.../composer.json) (revision 16637)
+++ branches/5.2.x/composer.json (.../composer.json) (revision 16691)
@@ -1,5 +1,11 @@
{
"name": "In-Portal",
+ "require": {
+ "php": ">=5.3.7",
+ "paragonie/random_compat": "^2.0",
+ "symfony/polyfill-php55": "^1.19",
+ "symfony/polyfill-php56": "^1.19"
+ },
"require-dev": {
"aik099/phpunit-mink": "^2.2",
"qa-tools/qa-tools": "^1.2",
Index: branches/5.2.x/core/install/prerequisites.php
===================================================================
diff -u -N -r16432 -r16691
--- branches/5.2.x/core/install/prerequisites.php (.../prerequisites.php) (revision 16432)
+++ branches/5.2.x/core/install/prerequisites.php (.../prerequisites.php) (revision 16691)
@@ -1,6 +1,6 @@
&1');
$ret['java'] = stripos($output, 'java version') !== false;
Index: branches/5.2.x/composer.lock
===================================================================
diff -u -N -r16637 -r16691
--- branches/5.2.x/composer.lock (.../composer.lock) (revision 16637)
+++ branches/5.2.x/composer.lock (.../composer.lock) (revision 16691)
@@ -4,8 +4,318 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "bdf85cd4a4719d9255c1eb5022f63706",
- "packages": [],
+ "content-hash": "ef20f3d542075e2d792fba4a7d3379c2",
+ "packages": [
+ {
+ "name": "ircmaxell/password-compat",
+ "version": "v1.0.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/ircmaxell/password_compat.git",
+ "reference": "5c5cde8822a69545767f7c7f3058cb15ff84614c"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/ircmaxell/password_compat/zipball/5c5cde8822a69545767f7c7f3058cb15ff84614c",
+ "reference": "5c5cde8822a69545767f7c7f3058cb15ff84614c",
+ "shasum": ""
+ },
+ "require-dev": {
+ "phpunit/phpunit": "4.*"
+ },
+ "type": "library",
+ "autoload": {
+ "files": [
+ "lib/password.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Anthony Ferrara",
+ "email": "ircmaxell@php.net",
+ "homepage": "http://blog.ircmaxell.com"
+ }
+ ],
+ "description": "A compatibility library for the proposed simplified password hashing algorithm: https://wiki.php.net/rfc/password_hash",
+ "homepage": "https://github.com/ircmaxell/password_compat",
+ "keywords": [
+ "hashing",
+ "password"
+ ],
+ "time": "2014-11-20T16:49:30+00:00"
+ },
+ {
+ "name": "paragonie/random_compat",
+ "version": "v2.0.19",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/paragonie/random_compat.git",
+ "reference": "446fc9faa5c2a9ddf65eb7121c0af7e857295241"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/paragonie/random_compat/zipball/446fc9faa5c2a9ddf65eb7121c0af7e857295241",
+ "reference": "446fc9faa5c2a9ddf65eb7121c0af7e857295241",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.2.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "4.*|5.*"
+ },
+ "suggest": {
+ "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes."
+ },
+ "type": "library",
+ "autoload": {
+ "files": [
+ "lib/random.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Paragon Initiative Enterprises",
+ "email": "security@paragonie.com",
+ "homepage": "https://paragonie.com"
+ }
+ ],
+ "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7",
+ "keywords": [
+ "csprng",
+ "polyfill",
+ "pseudorandom",
+ "random"
+ ],
+ "time": "2020-10-15T10:06:57+00:00"
+ },
+ {
+ "name": "symfony/polyfill-php55",
+ "version": "v1.19.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-php55.git",
+ "reference": "248a5c9877b126493abb661e4fb47792e418035b"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-php55/zipball/248a5c9877b126493abb661e4fb47792e418035b",
+ "reference": "248a5c9877b126493abb661e4fb47792e418035b",
+ "shasum": ""
+ },
+ "require": {
+ "ircmaxell/password-compat": "~1.0",
+ "php": ">=5.3.3"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "1.19-dev"
+ },
+ "thanks": {
+ "name": "symfony/polyfill",
+ "url": "https://github.com/symfony/polyfill"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Polyfill\\Php55\\": ""
+ },
+ "files": [
+ "bootstrap.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony polyfill backporting some PHP 5.5+ features to lower PHP versions",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "polyfill",
+ "portable",
+ "shim"
+ ],
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2020-10-23T09:01:57+00:00"
+ },
+ {
+ "name": "symfony/polyfill-php56",
+ "version": "v1.19.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-php56.git",
+ "reference": "ea19621731cbd973a6702cfedef3419768bf3372"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-php56/zipball/ea19621731cbd973a6702cfedef3419768bf3372",
+ "reference": "ea19621731cbd973a6702cfedef3419768bf3372",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3",
+ "symfony/polyfill-util": "~1.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "1.19-dev"
+ },
+ "thanks": {
+ "name": "symfony/polyfill",
+ "url": "https://github.com/symfony/polyfill"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Polyfill\\Php56\\": ""
+ },
+ "files": [
+ "bootstrap.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony polyfill backporting some PHP 5.6+ features to lower PHP versions",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "polyfill",
+ "portable",
+ "shim"
+ ],
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2020-10-23T09:01:57+00:00"
+ },
+ {
+ "name": "symfony/polyfill-util",
+ "version": "v1.19.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-util.git",
+ "reference": "8df0c3e6a4b85df9a5c6f3f2f46fba5c5c47058a"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-util/zipball/8df0c3e6a4b85df9a5c6f3f2f46fba5c5c47058a",
+ "reference": "8df0c3e6a4b85df9a5c6f3f2f46fba5c5c47058a",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "1.19-dev"
+ },
+ "thanks": {
+ "name": "symfony/polyfill",
+ "url": "https://github.com/symfony/polyfill"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Polyfill\\Util\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony utilities for portability of PHP codes",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compat",
+ "compatibility",
+ "polyfill",
+ "shim"
+ ],
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2020-10-21T09:57:48+00:00"
+ }
+ ],
"packages-dev": [
{
"name": "aik099/coding-standard",
@@ -747,6 +1057,7 @@
"keywords": [
"tokenizer"
],
+ "abandoned": true,
"time": "2017-12-04T08:55:13+00:00"
},
{
@@ -875,6 +1186,7 @@
"mock",
"xunit"
],
+ "abandoned": true,
"time": "2015-10-02T06:51:40+00:00"
},
{
@@ -1593,9 +1905,12 @@
},
"prefer-stable": false,
"prefer-lowest": false,
- "platform": [],
+ "platform": {
+ "php": ">=5.3.7"
+ },
"platform-dev": [],
"platform-overrides": {
"php": "5.3.7"
- }
+ },
+ "plugin-api-version": "1.1.0"
}
Index: branches/5.2.x/core/kernel/security/SecurityGenerator.php
===================================================================
diff -u -N
--- branches/5.2.x/core/kernel/security/SecurityGenerator.php (revision 0)
+++ branches/5.2.x/core/kernel/security/SecurityGenerator.php (revision 16691)
@@ -0,0 +1,193 @@
+ 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
+ self::CHAR_LOWER => 'abcdefghijklmnopqrstuvwxyz',
+ self::CHAR_DIGITS => '0123456789',
+ self::CHAR_UPPER_HEX => 'ABCDEF',
+ self::CHAR_LOWER_HEX => 'abcdef',
+ self::CHAR_BASE64 => '+/',
+ self::CHAR_SYMBOLS => '!"#$%&\'()* +,-./:;<=>?@[\]^_`{|}~',
+ self::CHAR_BRACKETS => '()[]{}<>',
+ self::CHAR_PUNCT => ',.;:',
+ );
+
+ /**
+ * Generate a random string of specified length using supplied character list.
+ *
+ * @param integer $length The length of the generated string.
+ * @param mixed $characters List of characters to use or character flags.
+ *
+ * @return SecurityGeneratorPromise
+ */
+ public static function generateString($length, $characters)
+ {
+ // Combine character sets.
+ if ( is_int($characters) ) {
+ $characters = self::expandCharacterSets($characters);
+ }
+
+ return new SecurityGeneratorPromise(
+ SecurityGeneratorPromise::TYPE_STRING,
+ array($length, $characters)
+ );
+ }
+
+ /**
+ * Expand a character set bitwise spec into a string character set.
+ * This will also replace EASY_TO_READ characters if the flag is set.
+ *
+ * @param integer $spec The spec to expand (bitwise combination of flags).
+ *
+ * @return string The expanded string
+ */
+ protected static function expandCharacterSets($spec)
+ {
+ $combined = '';
+
+ if ( $spec == self::EASY_TO_READ ) {
+ $spec |= self::CHAR_ALNUM;
+ }
+
+ foreach ( self::$charArrays as $flag => $chars ) {
+ // Handle this later.
+ if ( $flag == self::EASY_TO_READ ) {
+ continue;
+ }
+
+ if ( ($spec & $flag) === $flag ) {
+ $combined .= $chars;
+ }
+ }
+
+ // Remove ambiguous characters.
+ if ( $spec & self::EASY_TO_READ ) {
+ $combined = str_replace(str_split(self::AMBIGUOUS_CHARS), '', $combined);
+ }
+
+ return count_chars($combined, 3);
+ }
+
+ /**
+ * Generates a random number.
+ *
+ * @param integer $min Smallest value.
+ * @param integer $max Largest value.
+ *
+ * @return SecurityGeneratorPromise
+ */
+ public static function generateNumber($min, $max)
+ {
+ return new SecurityGeneratorPromise(
+ SecurityGeneratorPromise::TYPE_NUMBER,
+ array($min, $max)
+ );
+ }
+
+ /**
+ * Generates random bytes.
+ *
+ * @param integer $length Raw result length.
+ * @param boolean $raw_output Return raw result.
+ *
+ * @return SecurityGeneratorPromise
+ */
+ public static function generateBytes($length = 16, $raw_output = false)
+ {
+ return new SecurityGeneratorPromise(
+ SecurityGeneratorPromise::TYPE_BYTES,
+ array($length, $raw_output)
+ );
+ }
+
+}
Index: branches/5.2.x/core/kernel/security/SecurityEncrypter.php
===================================================================
diff -u -N
--- branches/5.2.x/core/kernel/security/SecurityEncrypter.php (revision 0)
+++ branches/5.2.x/core/kernel/security/SecurityEncrypter.php (revision 16691)
@@ -0,0 +1,228 @@
+getData();
+
+ // In the config data is encoded stored to avoid corruption.
+ $this->hmacKey = base64_decode($vars['SecurityHmacKey']);
+
+ // Equivalent of "hex2bin" for PHP < 5.4.
+ $this->encryptionKey = pack('H*', $vars['SecurityEncryptionKey']);
+ }
+
+ /**
+ * Creates signature.
+ *
+ * @param string $string String.
+ * @param boolean $raw_output Return raw signature version.
+ * @param string|null $key_override Override key.
+ *
+ * @return string
+ */
+ public function createSignature($string, $raw_output = false, $key_override = null)
+ {
+ return hash_hmac(self::HASHING_ALGORITHM, $string, $this->_getHmacKey($key_override), $raw_output);
+ }
+
+ /**
+ * Returns HMAC key.
+ *
+ * @param string|null $key_override Key override.
+ *
+ * @return string
+ * @throws InvalidArgumentException When HMAC key is empty.
+ */
+ private function _getHmacKey($key_override = null)
+ {
+ $key = $this->doGetHmacKey($key_override);
+
+ if ( empty($key) ) {
+ throw new InvalidArgumentException('The HMAC key is empty.');
+ }
+
+ if ( mb_strlen($key, '8bit') === self::HASHING_KEY_LENGTH ) {
+ return $key;
+ }
+
+ return $this->deriveKey($key, self::HASHING_KEY_LENGTH);
+ }
+
+ /**
+ * Returns HMAC key.
+ *
+ * @param string|null $key_override Key override.
+ *
+ * @return string
+ */
+ protected function doGetHmacKey($key_override = null)
+ {
+ return isset($key_override) ? $key_override : $this->hmacKey;
+ }
+
+ /**
+ * Returns encryption key.
+ *
+ * @param string|null $key_override Key override.
+ *
+ * @return string
+ * @throws InvalidArgumentException When encryption key is empty.
+ */
+ private function _getEncryptionKey($key_override = null)
+ {
+ $key = $this->doGetEncryptionKey($key_override);
+
+ if ( empty($key) ) {
+ throw new InvalidArgumentException('The encryption key is empty.');
+ }
+
+ if ( mb_strlen($key, '8bit') === self::ENCRYPTION_KEY_LENGTH ) {
+ return $key;
+ }
+
+ return $this->deriveKey($key, self::ENCRYPTION_KEY_LENGTH);
+ }
+
+ /**
+ * Returns encryption key.
+ *
+ * @param string|null $key_override Key override.
+ *
+ * @return string
+ */
+ protected function doGetEncryptionKey($key_override = null)
+ {
+ return isset($key_override) ? $key_override : $this->encryptionKey;
+ }
+
+ /**
+ * Derives given key.
+ *
+ * @param string $key Key.
+ * @param integer $length Length.
+ *
+ * @return string
+ */
+ final public function deriveKey($key, $length)
+ {
+ $salt = SecurityGenerator::generateBytes(16, true);
+
+ return hash_pbkdf2(self::HASHING_ALGORITHM, $key, $salt, 80000, $length, true);
+ }
+
+ /**
+ * Encrypts a plain text.
+ *
+ * @param string $plaintext Plain text.
+ * @param string|null $key_override Key override.
+ *
+ * @return string
+ */
+ final public function encrypt($plaintext, $key_override = null)
+ {
+ $iv_size = openssl_cipher_iv_length(self::ENCRYPTION_METHOD);
+ $iv = openssl_random_pseudo_bytes($iv_size);
+
+ $ciphertext = openssl_encrypt(
+ $plaintext,
+ self::ENCRYPTION_METHOD,
+ $this->_getEncryptionKey($key_override),
+ OPENSSL_RAW_DATA,
+ $iv
+ );
+
+ // Note: We cover the IV in our HMAC.
+ $hmac = $this->createSignature($iv . $ciphertext, true);
+
+ return base64_encode($hmac . $iv . $ciphertext);
+ }
+
+ /**
+ * Decrypts a cipher text.
+ *
+ * @param string $ciphertext Cipher text.
+ * @param string|null $key_override Key override.
+ *
+ * @return string|false
+ * @throws LogicException When signature verification has failed.
+ */
+ final public function decrypt($ciphertext, $key_override = null)
+ {
+ $iv_size = openssl_cipher_iv_length(self::ENCRYPTION_METHOD);
+
+ $decoded = base64_decode($ciphertext);
+ $hmac = mb_substr($decoded, 0, self::HASHING_KEY_LENGTH, '8bit');
+ $iv = mb_substr($decoded, self::HASHING_KEY_LENGTH, $iv_size, '8bit');
+ $ciphertext = mb_substr($decoded, self::HASHING_KEY_LENGTH + $iv_size, null, '8bit');
+
+ $calculated = $this->createSignature($iv . $ciphertext, true);
+
+ if ( !hash_equals($hmac, $calculated) ) {
+ throw new LogicException('Signature verification of ciphertext failed.');
+ }
+
+ return openssl_decrypt(
+ $ciphertext,
+ self::ENCRYPTION_METHOD,
+ $this->_getEncryptionKey($key_override),
+ OPENSSL_RAW_DATA,
+ $iv
+ );
+ }
+
+ /**
+ * Determines if used cipher is available.
+ *
+ * @return boolean
+ */
+ final public function cipherAvailable()
+ {
+ return in_array(self::ENCRYPTION_METHOD, openssl_get_cipher_methods(), true);
+ }
+
+}
Index: branches/5.2.x/core/kernel/application.php
===================================================================
diff -u -N -r16662 -r16691
--- branches/5.2.x/core/kernel/application.php (.../application.php) (revision 16662)
+++ branches/5.2.x/core/kernel/application.php (.../application.php) (revision 16691)
@@ -1,6 +1,6 @@
registerClass('kCache', KERNEL_PATH . '/utility/cache.php', 'kCache', 'Params');
$this->registerClass('kHTTPQuery', KERNEL_PATH . '/utility/http_query.php', 'HTTPQuery');
+ // security
+ $this->registerClass('SecurityGenerator', KERNEL_PATH . '/security/SecurityGenerator.php');
+ $this->registerClass('SecurityGeneratorPromise', KERNEL_PATH . '/security/SecurityGeneratorPromise.php');
+ $this->registerClass('SecurityEncrypter', KERNEL_PATH . '/security/SecurityEncrypter.php');
+
// session
$this->registerClass('Session', KERNEL_PATH . '/session/session.php');
$this->registerClass('SessionStorage', KERNEL_PATH . '/session/session_storage.php');
Index: branches/5.2.x/core/kernel/security/SecurityGeneratorPromise.php
===================================================================
diff -u -N
--- branches/5.2.x/core/kernel/security/SecurityGeneratorPromise.php (revision 0)
+++ branches/5.2.x/core/kernel/security/SecurityGeneratorPromise.php (revision 16691)
@@ -0,0 +1,274 @@
+ 'generateNumber',
+ self::TYPE_STRING => 'generateString',
+ self::TYPE_BYTES => 'generateBytes',
+ );
+
+ if ( !isset($mapping[$type]) ) {
+ throw new InvalidArgumentException('The "' . $type . '" promise type is not supported.');
+ }
+
+ $this->method = $mapping[$type];
+ $this->arguments = $arguments;
+ }
+
+ /**
+ * Makes sure, that resolved value isn't already used in the given database table's column.
+ *
+ * @param string $prefix_or_table Unit config prefix or table name.
+ * @param string $column Column in specified table.
+ *
+ * @return mixed
+ * @throws LogicException When after 10 retries still unable to generate unique value for database.
+ */
+ public function resolveForPersisting($prefix_or_table, $column)
+ {
+ $application =& kApplication::Instance();
+
+ if ( $application->prefixRegistred($prefix_or_table) ) {
+ $table = $application->getUnitOption($prefix_or_table, 'TableName');
+ }
+ else {
+ $table = $prefix_or_table;
+ }
+
+ $retries = 0;
+
+ do {
+ $resolved_value = $this->resolve();
+
+ $sql = 'SELECT ' . $column . '
+ FROM ' . $table . '
+ WHERE ' . $column . ' = ' . $application->Conn->qstr($resolved_value);
+ $found = $application->Conn->GetOne($sql) !== false;
+
+ if ( $found ) {
+ $this->resolvedValue = null;
+ $retries++;
+ }
+ } while ( $found && $retries < 10 );
+
+ if ( $found ) {
+ throw new LogicException(sprintf(
+ 'Unable to generate unique value for "%s" column with current generator configuration.',
+ $table . '.' . $column
+ ));
+ }
+
+ return $resolved_value;
+ }
+
+ /**
+ * Resolves a promise.
+ *
+ * @return mixed
+ */
+ public function resolve()
+ {
+ if ( !$this->isResolved() ) {
+ $this->resolvedValue = call_user_func_array(array($this, $this->method), $this->arguments);
+ }
+
+ if ( !$this->asSignature ) {
+ return $this->resolvedValue;
+ }
+
+ $application =& kApplication::Instance();
+
+ /** @var SecurityEncrypter $encrypter */
+ $encrypter = $application->recallObject('SecurityEncrypter');
+
+ return $encrypter->createSignature(
+ $this->resolvedValue,
+ $this->signatureRawOutput,
+ $this->signatureKeyOverride
+ );
+ }
+
+ /**
+ * Configures promise to return signature of a resolved value.
+ *
+ * @param boolean $raw_output Return raw signature value during resolving.
+ * @param string|null $key_override Alternative key used for creating signature of resolved value.
+ *
+ * @return self
+ */
+ public function asSignature($raw_output = false, $key_override = null)
+ {
+ $this->asSignature = true;
+ $this->signatureRawOutput = $raw_output;
+ $this->signatureKeyOverride = $key_override;
+
+ return $this;
+ }
+
+ /**
+ * Configures promise to return resolved value as-is.
+ *
+ * @return self
+ */
+ public function asValue()
+ {
+ $this->asSignature = false;
+ $this->signatureRawOutput = false;
+ $this->signatureKeyOverride = null;
+
+ return $this;
+ }
+
+ /**
+ * Generate a random string of specified length using supplied character list.
+ *
+ * @param integer $length The length of the generated string.
+ * @param mixed $characters List of characters to use.
+ *
+ * @return string
+ */
+ protected function generateString($length, $characters)
+ {
+ $ret = '';
+ $max_index = mb_strlen($characters) - 1;
+
+ for ( $i = 0; $i < $length; $i++ ) {
+ $ret .= mb_substr($characters, $this->generateNumber(0, $max_index), 1);
+ }
+
+ return $ret;
+ }
+
+ /**
+ * Generates a random number.
+ *
+ * @param integer $min Smallest value.
+ * @param integer $max Largest value.
+ *
+ * @return integer
+ */
+ protected function generateNumber($min, $max)
+ {
+ return random_int($min, $max);
+ }
+
+ /**
+ * Generates random bytes.
+ *
+ * @param integer $length Raw result length.
+ * @param boolean $raw_output Return raw result.
+ *
+ * @return string
+ */
+ protected function generateBytes($length = 16, $raw_output = false)
+ {
+ $ret = random_bytes($length);
+
+ return $raw_output ? $ret : bin2hex($ret);
+ }
+
+ /**
+ * Determines if promise was already resolved.
+ *
+ * @return boolean
+ */
+ protected function isResolved()
+ {
+ return $this->resolvedValue !== null;
+ }
+
+ /**
+ * Returns promise resolved value casted to string.
+ *
+ * @return string
+ */
+ public function __toString()
+ {
+ return (string)$this->resolve();
+ }
+
+}
Index: branches/5.2.x/core/install/step_templates/sys_requirements.tpl
===================================================================
diff -u -N -r16117 -r16691
--- branches/5.2.x/core/install/step_templates/sys_requirements.tpl (.../sys_requirements.tpl) (revision 16117)
+++ branches/5.2.x/core/install/step_templates/sys_requirements.tpl (.../sys_requirements.tpl) (revision 16691)
@@ -25,6 +25,7 @@
'jpeg' => '- JPEG images support*',
'mysql' => '- Database connectivity (via MySQL)*',
'json' => '- JSON processing support*',
+ 'openssl' => '- OpenSSL support*',
'sep2' => 'PHP settings:',
'memory_limit' => "- Memory requirements changing on the fly",
'display_errors' => "- Prevent script errors in production environment",
Index: branches/5.2.x/core/install.php
===================================================================
diff -u -N -r16689 -r16691
--- branches/5.2.x/core/install.php (.../install.php) (revision 16689)
+++ branches/5.2.x/core/install.php (.../install.php) (revision 16691)
@@ -1,6 +1,6 @@
toolkit->CallPrerequisitesMethod('core/', 'CheckSystemRequirements');
@@ -841,6 +841,24 @@
}
}
+ if ( !$this->toolkit->systemConfig->get('SecurityHmacKey', 'Misc')
+ || !$this->toolkit->systemConfig->get('SecurityEncryptionKey', 'Misc')
+ ) {
+ $this->toolkit->systemConfig->set(
+ 'SecurityHmacKey',
+ 'Misc',
+ base64_encode(SecurityGenerator::generateString(
+ SecurityEncrypter::HASHING_KEY_LENGTH,
+ SecurityGenerator::CHAR_ALNUM | SecurityGenerator::CHAR_SYMBOLS
+ ))
+ );
+ $this->toolkit->systemConfig->set(
+ 'SecurityEncryptionKey',
+ 'Misc',
+ SecurityGenerator::generateBytes(SecurityEncrypter::ENCRYPTION_KEY_LENGTH)
+ );
+ }
+
$this->toolkit->systemConfig->save();
break;
Index: branches/5.2.x/core/kernel/utility/system_config.php
===================================================================
diff -u -N -r16439 -r16691
--- branches/5.2.x/core/kernel/utility/system_config.php (.../system_config.php) (revision 16439)
+++ branches/5.2.x/core/kernel/utility/system_config.php (.../system_config.php) (revision 16691)
@@ -84,6 +84,8 @@
'WebsiteCharset' => 'utf-8',
'WebsitePath' => rtrim(preg_replace('/'.preg_quote(rtrim(defined('REL_PATH') ? REL_PATH : '', '/'), '/').'$/', '', str_replace('\\', '/', dirname($_SERVER['PHP_SELF']))), '/'),
'WriteablePath' => DIRECTORY_SEPARATOR . 'system',
+ 'SecurityHmacKey' => '',
+ 'SecurityEncryptionKey' => '',
);
return $this->parseSections ? array('Misc' => $ret) : $ret;