From faaff420969485075fc85901c391c399f1b58d8c Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Tue, 8 May 2018 09:04:52 +0200 Subject: [PATCH 1/3] Revert "Introduce PasswordHelper for safer passwords" This reverts commit f57277aa96ce91a0e6761b04937447b9a2a9a679. Since we're dropping PHP support for versions lower than 5.6 this class is no longer necessary. --- .../Icinga/Authentication/PasswordHelper.php | 109 ------------------ .../Authentication/PasswordHelperTest.php | 92 --------------- 2 files changed, 201 deletions(-) delete mode 100644 library/Icinga/Authentication/PasswordHelper.php delete mode 100644 test/php/library/Icinga/Authentication/PasswordHelperTest.php diff --git a/library/Icinga/Authentication/PasswordHelper.php b/library/Icinga/Authentication/PasswordHelper.php deleted file mode 100644 index 0f5448b70..000000000 --- a/library/Icinga/Authentication/PasswordHelper.php +++ /dev/null @@ -1,109 +0,0 @@ -='); - } - - /** - * Hash a password with password_hash() or crypt() - * - * @param string $password - * @param int $algo - * - * @return string - * @throws AuthenticationException - */ - public static function hash($password, $algo = null) - { - if (static::supportsModernAPI() and $algo !== self::PASSWORD_ALGO_FALLBACK) { - if ($algo === null) { - $algo = PASSWORD_DEFAULT; - } - $p = password_hash($password, $algo); - if ($p === false) { - throw new AuthenticationException('Could not hash password, password_hash() returned false!'); - } - } else { - $p = crypt($password, self::COMPAT_HASH . static::generateSalt()); - if (strlen($p) < 13) { - throw new AuthenticationException('Hash generated by crypt() seems too small, this suggests an error!'); - } - } - - return $p; - } - - /** - * Verify a password with either password_verify() or crypt() - * - * @param string $password - * @param string $hash - * - * @return bool - */ - public static function verify($password, $hash) - { - if (static::supportsModernAPI()) { - return password_verify($password, $hash); - } else { - return crypt($password, $hash) === $hash; - } - } - - /** - * Shorthand to generate a salt to use with crypt() - * - * @return string - */ - public static function generateSalt() - { - return bin2hex(openssl_random_pseudo_bytes(self::COMPAT_SALT_LENGTH / 2)); - } -} diff --git a/test/php/library/Icinga/Authentication/PasswordHelperTest.php b/test/php/library/Icinga/Authentication/PasswordHelperTest.php deleted file mode 100644 index 7c97edda3..000000000 --- a/test/php/library/Icinga/Authentication/PasswordHelperTest.php +++ /dev/null @@ -1,92 +0,0 @@ -assertRegExp( - '~^[a-f0-9]{16}$~i', - PasswordHelper::generateSalt(), - 'A hex based salt with 16 chars must be returned' - ); - } - - public function testHash() - { - foreach (array(self::TEST_PASSWORD, self::TEST_PASSWORD_LONG) as $pw) { - $hashed = PasswordHelper::hash($pw); - - $this->assertRegExp( - '~^\$\d\w*\$(?:rounds=\d+\$)?~', - $hashed, - 'Hash output must look like a hash: ' . $hashed - ); - - $this->assertEquals( - crypt($pw, $hashed), - $hashed, - 'New hashed password must validate via crypt: ' . $hashed - ); - } - } - - public function testHashFallback() - { - $hashed = PasswordHelper::hash(self::TEST_PASSWORD, PasswordHelper::PASSWORD_ALGO_FALLBACK); - - $this->assertRegExp( - '~^\$6\$rounds=\d+\$?~', - $hashed, - 'Hash output must look like a SHA-512 hash: ' . $hashed - ); - - $this->assertEquals( - crypt(self::TEST_PASSWORD, $hashed), - $hashed, - 'New hashed password must validate via crypt: ' . $hashed - ); - } - - public function testVerify() - { - $pws = array( - self::TEST_PASSWORD_HASHED_BLOWFISH_1 => self::TEST_PASSWORD, - self::TEST_PASSWORD_HASHED_BLOWFISH_2 => self::TEST_PASSWORD, - self::TEST_PASSWORD_HASHED_BLOWFISH_LONG => self::TEST_PASSWORD_LONG, - self::TEST_PASSWORD_HASHED_SHA256 => self::TEST_PASSWORD, - pack('H*', self::TEST_PASSWORD_OLD_MD5) => self::TEST_PASSWORD, - ); - - foreach ($pws as $hash => $pw) { - $this->assertTrue( - PasswordHelper::verify($pw, $hash), - 'Password must be validated against its hash' - ); - } - } -} From d6c4df7a5d01cd6922d20ad3eeb8500f59bc8095 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Tue, 8 May 2018 09:06:19 +0200 Subject: [PATCH 2/3] Use password_hash and password_verify --- library/Icinga/Authentication/User/DbUserBackend.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/library/Icinga/Authentication/User/DbUserBackend.php b/library/Icinga/Authentication/User/DbUserBackend.php index 8cf4f5f40..35a0c3cc6 100644 --- a/library/Icinga/Authentication/User/DbUserBackend.php +++ b/library/Icinga/Authentication/User/DbUserBackend.php @@ -4,7 +4,6 @@ namespace Icinga\Authentication\User; use Exception; -use Icinga\Authentication\PasswordHelper; use Icinga\Data\Inspectable; use Icinga\Data\Inspection; use Icinga\Data\Filter\Filter; @@ -166,7 +165,7 @@ class DbUserBackend extends DbRepository implements UserBackendInterface, Inspec */ protected function persistPassword($value) { - return PasswordHelper::hash($value); + return password_hash($value, PASSWORD_DEFAULT); } /** @@ -213,7 +212,7 @@ class DbUserBackend extends DbRepository implements UserBackendInterface, Inspec public function authenticate(User $user, $password) { try { - return PasswordHelper::verify( + return password_verify( $password, $this->getPasswordHash($user->getUsername()) ); From 8990d6f46e699e649a62213bfe0ef20772207ce2 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Tue, 8 May 2018 09:16:47 +0200 Subject: [PATCH 3/3] Drop support for PHP < 5.6 --- .travis.yml | 2 - doc/02-Installation.md | 4 +- library/Icinga/Util/Json.php | 38 ++----------------- .../locale/de_DE/LC_MESSAGES/setup.po | 4 +- .../locale/it_IT/LC_MESSAGES/setup.po | 6 +-- modules/setup/library/Setup/WebWizard.php | 4 +- test/setup_vendor.sh | 8 +--- 7 files changed, 12 insertions(+), 54 deletions(-) diff --git a/.travis.yml b/.travis.yml index 058492b05..7dd22e111 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,8 +3,6 @@ dist: trusty sudo: false php: - - '5.4' - - '5.5' - '5.6' - '7.0' - '7.1' diff --git a/doc/02-Installation.md b/doc/02-Installation.md index 806dde6d6..7fb492caa 100644 --- a/doc/02-Installation.md +++ b/doc/02-Installation.md @@ -14,9 +14,7 @@ chapter. * [Icinga 2](https://www.icinga.com/products/icinga-2/) with the IDO database backend (MySQL or PostgreSQL) * A web server, e.g. Apache or Nginx -* PHP version >= 5.6.0. Though Icinga Web 2 version 2.5.x is compatible with PHP version >= 5.3.2 there are modules - which require a higher PHP version. Also, future versions of Icinga Web 2 will drop support for outdated PHP versions. - Packages for Icinga Web 2 already require PHP >= 5.6.0 +* PHP version >= 5.6.0 * The following PHP modules must be installed: cURL, gettext, intl, mbstring, OpenSSL and xml * Default time zone configured for PHP in the php.ini file * LDAP PHP library when using Active Directory or LDAP for authentication diff --git a/library/Icinga/Util/Json.php b/library/Icinga/Util/Json.php index a04883a08..1cd69e6e4 100644 --- a/library/Icinga/Util/Json.php +++ b/library/Icinga/Util/Json.php @@ -54,11 +54,7 @@ class Json */ protected static function encodeAndSanitize($value, $options, $depth, $autoSanitize) { - if (version_compare(phpversion(), '5.5.0', '<')) { - $encoded = json_encode($value, $options); - } else { - $encoded = json_encode($value, $options, $depth); - } + $encoded = json_encode($value, $options, $depth); switch (json_last_error()) { case JSON_ERROR_NONE: @@ -72,7 +68,7 @@ class Json // Fallthrough default: - throw new JsonEncodeException('%s: %s', static::lastErrorMsg(), var_export($value, true)); + throw new JsonEncodeException('%s: %s', json_last_error_msg(), var_export($value, true)); } } @@ -92,39 +88,11 @@ class Json $decoded = json_decode($json, $assoc, $depth, $options); if (json_last_error() !== JSON_ERROR_NONE) { - throw new JsonDecodeException('%s: %s', static::lastErrorMsg(), var_export($json, true)); + throw new JsonDecodeException('%s: %s', json_last_error_msg(), var_export($json, true)); } return $decoded; } - /** - * {@link json_last_error_msg()} replacement for PHP < 5.5.0 - * - * @return string - */ - protected static function lastErrorMsg() - { - if (version_compare(PHP_VERSION, '5.5.0', '>=')) { - return json_last_error_msg(); - } - - // All possible error codes before PHP 5.5.0 (except JSON_ERROR_NONE) - switch (json_last_error()) { - case JSON_ERROR_DEPTH: - return 'Maximum stack depth exceeded'; - case JSON_ERROR_STATE_MISMATCH: - return 'State mismatch (invalid or malformed JSON)'; - case JSON_ERROR_CTRL_CHAR: - return 'Control character error, possibly incorrectly encoded'; - case JSON_ERROR_SYNTAX: - return 'Syntax error'; - case JSON_ERROR_UTF8: - return 'Malformed UTF-8 characters, possibly incorrectly encoded'; - default: - return 'Unknown error'; - } - } - /** * Replace bad byte sequences in UTF-8 strings inside the given JSON-encodable structure with question marks * diff --git a/modules/setup/application/locale/de_DE/LC_MESSAGES/setup.po b/modules/setup/application/locale/de_DE/LC_MESSAGES/setup.po index 17d2742d2..a61e7c0df 100644 --- a/modules/setup/application/locale/de_DE/LC_MESSAGES/setup.po +++ b/modules/setup/application/locale/de_DE/LC_MESSAGES/setup.po @@ -884,9 +884,9 @@ msgstr "Root DN" #: ../../../../modules/setup/library/Setup/WebWizard.php:556 msgid "" -"Running Icinga Web 2 requires PHP version 5.4." +"Running Icinga Web 2 requires PHP version 5.6." msgstr "" -"Der Betrieb von Icinga Web 2 erfordert die PHP-Version 5.4." +"Der Betrieb von Icinga Web 2 erfordert die PHP-Version 5.6." #: ../../../../modules/setup/library/Setup/Steps/ResourceStep.php:104 msgid "SSL Cert" diff --git a/modules/setup/application/locale/it_IT/LC_MESSAGES/setup.po b/modules/setup/application/locale/it_IT/LC_MESSAGES/setup.po index ec1d04b3c..3ecff2bff 100644 --- a/modules/setup/application/locale/it_IT/LC_MESSAGES/setup.po +++ b/modules/setup/application/locale/it_IT/LC_MESSAGES/setup.po @@ -2,7 +2,7 @@ # Copyright (C) 2015 Icinga Development Team # This file is distributed under the same license as Setup Module. # FIRST AUTHOR , YEAR. -# +# #, fuzzy msgid "" msgstr "" @@ -862,9 +862,9 @@ msgstr "Root DN" #: /usr/share/icingaweb2/modules/setup/library/Setup/WebWizard.php:552 msgid "" -"Running Icinga Web 2 requires PHP version 5.4." +"Running Icinga Web 2 requires PHP version 5.6." msgstr "" -"Icinga Web 2 richiede PHP 5.4." +"Icinga Web 2 richiede PHP 5.6." #: /usr/share/icingaweb2/modules/setup/library/Setup/WebWizard.php:356 msgid "Setup Icinga Web 2" diff --git a/modules/setup/library/Setup/WebWizard.php b/modules/setup/library/Setup/WebWizard.php index 2181cab59..597aa17e7 100644 --- a/modules/setup/library/Setup/WebWizard.php +++ b/modules/setup/library/Setup/WebWizard.php @@ -568,10 +568,10 @@ class WebWizard extends Wizard implements SetupWizard $set = new RequirementSet(); $set->add(new PhpVersionRequirement(array( - 'condition' => array('>=', '5.4'), + 'condition' => array('>=', '5.6'), 'description' => mt( 'setup', - 'Running Icinga Web 2 requires PHP version 5.4.' + 'Running Icinga Web 2 requires PHP version 5.6.' ) ))); diff --git a/test/setup_vendor.sh b/test/setup_vendor.sh index 663db8000..cf77de3bf 100755 --- a/test/setup_vendor.sh +++ b/test/setup_vendor.sh @@ -3,16 +3,10 @@ set -ex ICINGAWEB_HOME=${ICINGAWEB_HOME:="$(dirname "$(readlink -f $(dirname "$0"))")"} -PHP_VERSION="$(php -r 'echo phpversion();')" PHPCS_VERSION=${PHPCS_VERSION:=3.0.2} MOCKERY_VERSION=${MOCKERY_VERSION:=0.9.9} HAMCREST_VERSION=${HAMCREST_VERSION:=2.0.0} - -if [ "$PHP_VERSION" '<' 5.6.0 ]; then - PHPUNIT_VERSION=${PHPUNIT_VERSION:=4.8} -else - PHPUNIT_VERSION=${PHPUNIT_VERSION:=5.7} -fi +PHPUNIT_VERSION=${PHPUNIT_VERSION:=5.7} cd ${ICINGAWEB_HOME}