[FEATURE] Adjust trustedHostsPattern during installation 43/41143/4
authorNicole Cordes <typo3@cordes.co>
Mon, 13 Jul 2015 19:28:21 +0000 (21:28 +0200)
committerBenjamin Mack <benni@typo3.org>
Wed, 15 Jul 2015 18:38:12 +0000 (20:38 +0200)
During the installation the trusted hosts pattern check is disabled
by default. This leads to an exception after the installation on entering
the login form. This patch adds hosts checks to install tool and reports
module to ensure the installation is working after install process.

Releases: master
Resolves: #68096
Change-Id: I25a39b36d0922906c0ea2dec34b58b3c3fe805b7
Reviewed-on: http://review.typo3.org/41143
Reviewed-by: Mathias Schreiber <mathias.schreiber@wmdb.de>
Tested-by: Mathias Schreiber <mathias.schreiber@wmdb.de>
Reviewed-by: Benjamin Mack <benni@typo3.org>
Tested-by: Benjamin Mack <benni@typo3.org>
typo3/sysext/core/Classes/Utility/GeneralUtility.php
typo3/sysext/install/Classes/Controller/StepController.php
typo3/sysext/install/Classes/SystemEnvironment/Check.php
typo3/sysext/lang/locallang_core.xlf
typo3/sysext/reports/Classes/Report/Status/SecurityStatus.php
typo3/sysext/reports/reports/locallang.xlf

index d133292..50df1d2 100755 (executable)
@@ -3512,6 +3512,7 @@ Connection: close
        /**
         * Checks if the provided host header value matches the trusted hosts pattern.
         * If the pattern is not defined (which only can happen early in the bootstrap), deny any value.
+        * The result is saved, so the check needs to be executed only once.
         *
         * @param string $hostHeaderValue HTTP_HOST header value as sent during the request (may include port)
         * @return bool
@@ -3532,23 +3533,38 @@ Connection: close
 
                if ($GLOBALS['TYPO3_CONF_VARS']['SYS']['trustedHostsPattern'] === self::ENV_TRUSTED_HOSTS_PATTERN_ALLOW_ALL) {
                        static::$allowHostHeaderValue = TRUE;
-               } elseif ($GLOBALS['TYPO3_CONF_VARS']['SYS']['trustedHostsPattern'] === self::ENV_TRUSTED_HOSTS_PATTERN_SERVER_NAME) {
+               } else {
+                       static::$allowHostHeaderValue = static::hostHeaderValueMatchesTrustedHostsPattern($hostHeaderValue);
+               }
+
+               return static::$allowHostHeaderValue;
+       }
+
+       /**
+        * Checks if the provided host header value matches the trusted hosts pattern without any preprocessing.
+        *
+        * @param string $hostHeaderValue
+        * @return bool
+        * @internal
+        */
+       static public function hostHeaderValueMatchesTrustedHostsPattern($hostHeaderValue) {
+               if ($GLOBALS['TYPO3_CONF_VARS']['SYS']['trustedHostsPattern'] === self::ENV_TRUSTED_HOSTS_PATTERN_SERVER_NAME) {
                        // Allow values that equal the server name
                        // Note that this is only secure if name base virtual host are configured correctly in the webserver
                        $defaultPort = self::getIndpEnv('TYPO3_SSL') ? '443' : '80';
                        $parsedHostValue = parse_url('http://' . $hostHeaderValue);
                        if (isset($parsedHostValue['port'])) {
-                               static::$allowHostHeaderValue = (strtolower($parsedHostValue['host']) === strtolower($_SERVER['SERVER_NAME']) && (string)$parsedHostValue['port'] === $_SERVER['SERVER_PORT']);
+                               $hostMatch = (strtolower($parsedHostValue['host']) === strtolower($_SERVER['SERVER_NAME']) && (string)$parsedHostValue['port'] === $_SERVER['SERVER_PORT']);
                        } else {
-                               static::$allowHostHeaderValue = (strtolower($hostHeaderValue) === strtolower($_SERVER['SERVER_NAME']) && $defaultPort === $_SERVER['SERVER_PORT']);
+                               $hostMatch = (strtolower($hostHeaderValue) === strtolower($_SERVER['SERVER_NAME']) && $defaultPort === $_SERVER['SERVER_PORT']);
                        }
                } else {
                        // In case name based virtual hosts are not possible, we allow setting a trusted host pattern
                        // See https://typo3.org/teams/security/security-bulletins/typo3-core/typo3-core-sa-2014-001/ for further details
-                       static::$allowHostHeaderValue = (bool)preg_match('/^' . $GLOBALS['TYPO3_CONF_VARS']['SYS']['trustedHostsPattern'] . '$/i', $hostHeaderValue);
+                       $hostMatch = (bool)preg_match('/^' . $GLOBALS['TYPO3_CONF_VARS']['SYS']['trustedHostsPattern'] . '$/i', $hostHeaderValue);
                }
 
-               return static::$allowHostHeaderValue;
+               return $hostMatch;
        }
 
        /**
index 982aed6..5dbda42 100644 (file)
@@ -50,6 +50,7 @@ class StepController extends AbstractController {
                $this->outputInstallToolPasswordNotSetMessageIfNeeded();
                $this->recreatePackageStatesFileIfNotExisting();
                $this->executeOrOutputFirstInstallStepIfNeeded();
+               $this->adjustTrustedHostsPatternIfNeeded();
                $this->executeSilentConfigurationUpgradesIfNeeded();
                $this->initializeSession();
                $this->checkSessionToken();
@@ -295,6 +296,20 @@ class StepController extends AbstractController {
        }
 
        /**
+        * Checks the trusted hosts pattern setting
+        */
+       protected function adjustTrustedHostsPatternIfNeeded() {
+               if (GeneralUtility::hostHeaderValueMatchesTrustedHostsPattern($_SERVER['HTTP_HOST'])) {
+                       return;
+               }
+
+               /** @var \TYPO3\CMS\Core\Configuration\ConfigurationManager $configurationManager */
+               $configurationManager = $this->objectManager->get(\TYPO3\CMS\Core\Configuration\ConfigurationManager::class);
+               $configurationManager->setLocalConfigurationValueByPath('SYS/trustedHostsPattern', '.*');
+               $this->redirect();
+       }
+
+       /**
         * Call silent upgrade class, redirect to self if configuration was changed.
         *
         * @return void
index 9b6e1cb..c4eaa52 100644 (file)
@@ -76,6 +76,7 @@ class Check {
        public function getStatus() {
                $statusArray = array();
                $statusArray[] = $this->checkCurrentDirectoryIsInIncludePath();
+               $statusArray[] = $this->checkTrustedHostPattern();
                $statusArray[] = $this->checkFileUploadEnabled();
                $statusArray[] = $this->checkMaximumFileUploadSize();
                $statusArray[] = $this->checkPostUploadSizeIsHigherOrEqualMaximumFileUploadSize();
@@ -147,6 +148,30 @@ class Check {
        }
 
        /**
+        * Checks the status of the trusted hosts pattern check
+        *
+        * @return Status\StatusInterface
+        */
+       protected function checkTrustedHostPattern() {
+               if ($GLOBALS['TYPO3_CONF_VARS']['SYS']['trustedHostsPattern'] === GeneralUtility::ENV_TRUSTED_HOSTS_PATTERN_ALLOW_ALL) {
+                       $status = new Status\WarningStatus();
+                       $status->setTitle('Trusted hosts pattern is insecure');
+                       $status->setMessage('Trusted hosts pattern is configured to allow all header values. Check the pattern defined in Install Tool -> All configuration -> System -> trustedHostsPattern and adapt it to expected host value(s).');
+               } else {
+                       if (GeneralUtility::hostHeaderValueMatchesTrustedHostsPattern($_SERVER['HTTP_HOST'])) {
+                               $status = new Status\OkStatus();
+                               $status->setTitle('Trusted hosts pattern is configured to allow current host value.');
+                       } else {
+                               $status = new Status\ErrorStatus();
+                               $status->setTitle('Trusted hosts pattern mismatch');
+                               $status->setMessage('The trusted hosts pattern will be configured to allow all header values. This is because your $SERVER_NAME is "' . htmlspecialchars($_SERVER['SERVER_NAME']) . '" while your HTTP_HOST is "'. htmlspecialchars($_SERVER['HTTP_HOST']) . '". Check the pattern defined in Install Tool -> All configuration -> System -> trustedHostsPattern and adapt it to expected host value(s).');
+                       }
+               }
+
+               return $status;
+       }
+
+       /**
         * Check if file uploads are enabled in PHP
         *
         * @return Status\StatusInterface
index 5bc0c12..3b56df8 100644 (file)
@@ -1003,6 +1003,9 @@ Would you like to save now in order to refresh the display?</source>
                        <trans-unit id="warning.install_enabled_cmd">
                                <source>Click to remove the file now!</source>
                        </trans-unit>
+                       <trans-unit id="warning.install_trustedhosts">
+                               <source>The trusted hosts pattern check is disabled. Please define the allowed hosts in the [SYS][trustedHostsPattern] section of the Install Tool.</source>
+                       </trans-unit>
                        <trans-unit id="warning.install_encryption">
                                <source>The encryption key is not set. Set it in the %sBasic Configuration section%s of the Install Tool.</source>
                        </trans-unit>
index 1acfaa3..5fcab42 100644 (file)
@@ -31,6 +31,7 @@ class SecurityStatus implements \TYPO3\CMS\Reports\StatusProviderInterface {
         */
        public function getStatus() {
                $statuses = array(
+                       'trustedHostsPattern' => $this->getTrustedHostsPatternStatus(),
                        'adminUserAccount' => $this->getAdminAccountStatus(),
                        'encryptionKeyEmpty' => $this->getEncryptionKeyStatus(),
                        'fileDenyPattern' => $this->getFileDenyPatternStatus(),
@@ -41,6 +42,24 @@ class SecurityStatus implements \TYPO3\CMS\Reports\StatusProviderInterface {
        }
 
        /**
+        * Checks if the trusted hosts pattern check is disabled.
+        *
+        * @return \TYPO3\CMS\Reports\Status An object representing whether the check is disabled
+        */
+       protected function getTrustedHostsPatternStatus() {
+               $value = $GLOBALS['LANG']->getLL('status_ok');
+               $message = '';
+               $severity = \TYPO3\CMS\Reports\Status::OK;
+               if ($GLOBALS['TYPO3_CONF_VARS']['SYS']['trustedHostsPattern'] === GeneralUtility::ENV_TRUSTED_HOSTS_PATTERN_ALLOW_ALL) {
+                       $value = $GLOBALS['LANG']->getLL('status_insecure');
+                       $severity = \TYPO3\CMS\Reports\Status::ERROR;
+                       $message = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:warning.install_trustedhosts');
+               }
+               return GeneralUtility::makeInstance(\TYPO3\CMS\Reports\Status::class,
+                       $GLOBALS['LANG']->getLL('status_trustedHostsPattern'), $value, $message, $severity);
+       }
+
+       /**
         * Checks whether a an BE user account named admin with default password exists.
         *
         * @return \TYPO3\CMS\Reports\Status An object representing whether a default admin account exists
@@ -120,7 +139,6 @@ class SecurityStatus implements \TYPO3\CMS\Reports\StatusProviderInterface {
                if ($defaultParts !== $result) {
                        $value = $GLOBALS['LANG']->getLL('status_insecure');
                        $severity = \TYPO3\CMS\Reports\Status::ERROR;
-                       $url = 'install/index.php?redirect_url=index.php' . urlencode('?TYPO3_INSTALL[type]=config#set_encryptionKey');
                        $message = sprintf($GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:warning.file_deny_pattern_partsNotPresent'),
                                '<br /><pre>' . htmlspecialchars(FILE_DENY_PATTERN_DEFAULT) . '</pre><br />');
                }
index 9a8fe93..e45f605 100644 (file)
@@ -96,6 +96,9 @@
                        <trans-unit id="status_CreatedDirectoryPermissions.writable">
                                <source>Directories created by TYPO3 are configured to be world writable. Depending on your server configuration, this can be a security risk. It is usually better to configure the create mask to not allow writing to directories by "others". A sane default is often '2770' for $GLOBALS['TYPO3_CONF_VARS']['BE']['folderCreateMask']. This can be set in the install tool.</source>
                        </trans-unit>
+                       <trans-unit id="status_trustedHostsPattern">
+                               <source>Trusted Hosts Pattern</source>
+                       </trans-unit>
                        <trans-unit id="status_adminUserAccount">
                                <source>Admin User Account</source>
                        </trans-unit>