diff --git a/installation/model/database.php b/installation/model/database.php index 271366371c3ed..9014d209679da 100644 --- a/installation/model/database.php +++ b/installation/model/database.php @@ -79,6 +79,146 @@ public static function getUserId() return self::$userId; } + /** + * Checks the SecurityFile + * + * @return boolean true if all checks have been passed + * + * @since __DEPLOY_VERSION__ + */ + private function checkSecurityFile() + { + $securityFileCheckPassed = JFactory::getSession()->get('securityFileCheckPassed', false); + + // When all checks have been passed we don't need to do this here again. + if ($securityFileCheckPassed === false) + { + $generalRemoteDatabaseMessage = JText::sprintf( + 'INSTL_DATABASE_HOST_IS_NOT_LOCALHOST_GENERAL_MESSAGE', + 'https://docs.joomla.org/Special:MyLanguage/J3.x:Secured_procedure_for_installing_Joomla_with_a_remote_database' + ); + + $securityFile = JFactory::getSession()->get('securityFile', false); + + if ($securityFile === false) + { + // Add the general message + JFactory::getApplication()->enqueueMessage($generalRemoteDatabaseMessage, 'warning'); + + // This is the file you need to remove if you want to use a remote database + $securityFile = '_Joomla' . JUserHelper::genRandomPassword(21) . '.txt'; + JFactory::getSession()->set('securityFile', $securityFile); + + // Get the path + $securityFilePath = JPATH_INSTALLATION . '/' . $securityFile; + + // When the path is not writable the user needs to create the file manually + if (!JFile::write($securityFilePath, '')) + { + // Request to create the file manually + JFactory::getApplication()->enqueueMessage( + JText::sprintf( + 'INSTL_DATABASE_HOST_IS_NOT_LOCALHOST_CREATE_FILE', + $securityFile, + 'installation' + ), + 'error' + ); + + JFactory::getSession()->set('securityFileUnwritable', true); + + return false; + } + + // Save the file name to the session + JFactory::getSession()->set('securityFileWrittenByJoomla', true); + + // Request to delete that file + JFactory::getApplication()->enqueueMessage( + JText::sprintf( + 'INSTL_DATABASE_HOST_IS_NOT_LOCALHOST_DELETE_FILE', + $securityFile, + 'installation' + ), + 'error' + ); + + return false; + } + + if (JFactory::getSession()->get('securityFileWrittenByJoomla', false) === true && file_exists(JPATH_INSTALLATION . '/' . $securityFile)) + { + // Add the general message + JFactory::getApplication()->enqueueMessage($generalRemoteDatabaseMessage, 'warning'); + + JFactory::getApplication()->enqueueMessage( + JText::sprintf( + 'INSTL_DATABASE_HOST_IS_NOT_LOCALHOST_DELETE_FILE', + $securityFile, + 'installation' + ), + 'error' + ); + + return false; + } + + if (JFactory::getSession()->get('securityFileUnwritable', false) === true && !file_exists(JPATH_INSTALLATION . '/' . $securityFile)) + { + // Add the general message + JFactory::getApplication()->enqueueMessage($generalRemoteDatabaseMessage, 'warning'); + + JFactory::getApplication()->enqueueMessage( + JText::sprintf( + 'INSTL_DATABASE_HOST_IS_NOT_LOCALHOST_CREATE_FILE', + $securityFile, + 'installation' + ), + 'error' + ); + + return false; + } + + // All tests for this session passed set it to the session + JFactory::getSession()->set('securityFileCheckPassed', true); + } + } + + /** + * Checks the remote db_host and http_host for security reason + * + * @param object &$options The options reference to use for configuration. + * + * @return boolean true if all security checks have been passed + * + * @since __DEPLOY_VERSION__ + */ + private function checkHostSecurity(&$options) + { + $shouldCheckLocalhost = getenv('JOOMLA_INSTALLATION_DISABLE_LOCALHOST_CHECK') !== '1'; + + if (!$shouldCheckLocalhost) + { + return true; + } + + // Per Default allowed DB Hosts + $localhost = array( + 'localhost', + '127.0.0.1', + '::1', + ); + + $uri = JUri::getInstance(); + + // HTTP Status Code + $statusCode = JHttpFactory::getHttp()->get((string) $uri)->code; + + // Check if the db_host is safe or HTTP status code is 401 (HTTP authentication required) + return in_array($options->db_host, $localhost) || $statusCode == 401 + } + /** * Method to initialise the database. * @@ -164,112 +304,12 @@ public function initialise($options) return false; } - $shouldCheckLocalhost = getenv('JOOMLA_INSTALLATION_DISABLE_LOCALHOST_CHECK') !== '1'; - - // Per Default allowed DB Hosts - $localhost = array( - 'localhost', - '127.0.0.1', - '::1', - ); - - // Check the security file if the db_host is not localhost / 127.0.0.1 / ::1 - if ($shouldCheckLocalhost && !in_array($options->db_host, $localhost)) + // Save host checks + if ($this->checkHostSecurity($options) === false) { - $remoteDbFileTestsPassed = JFactory::getSession()->get('remoteDbFileTestsPassed', false); - - // When all checks have been passed we don't need to do this here again. - if ($remoteDbFileTestsPassed === false) + if ($this->checkSecurityFile() === false) { - $generalRemoteDatabaseMessage = JText::sprintf( - 'INSTL_DATABASE_HOST_IS_NOT_LOCALHOST_GENERAL_MESSAGE', - 'https://docs.joomla.org/Special:MyLanguage/J3.x:Secured_procedure_for_installing_Joomla_with_a_remote_database' - ); - - $remoteDbFile = JFactory::getSession()->get('remoteDbFile', false); - - if ($remoteDbFile === false) - { - // Add the general message - JFactory::getApplication()->enqueueMessage($generalRemoteDatabaseMessage, 'warning'); - - // This is the file you need to remove if you want to use a remote database - $remoteDbFile = '_Joomla' . JUserHelper::genRandomPassword(21) . '.txt'; - JFactory::getSession()->set('remoteDbFile', $remoteDbFile); - - // Get the path - $remoteDbPath = JPATH_INSTALLATION . '/' . $remoteDbFile; - - // When the path is not writable the user needs to create the file manually - if (!JFile::write($remoteDbPath, '')) - { - // Request to create the file manually - JFactory::getApplication()->enqueueMessage( - JText::sprintf( - 'INSTL_DATABASE_HOST_IS_NOT_LOCALHOST_CREATE_FILE', - $remoteDbFile, - 'installation' - ), - 'error' - ); - - JFactory::getSession()->set('remoteDbFileUnwritable', true); - - return false; - } - - // Save the file name to the session - JFactory::getSession()->set('remoteDbFileWrittenByJoomla', true); - - // Request to delete that file - JFactory::getApplication()->enqueueMessage( - JText::sprintf( - 'INSTL_DATABASE_HOST_IS_NOT_LOCALHOST_DELETE_FILE', - $remoteDbFile, - 'installation' - ), - 'error' - ); - - return false; - } - - if (JFactory::getSession()->get('remoteDbFileWrittenByJoomla', false) === true && file_exists(JPATH_INSTALLATION . '/' . $remoteDbFile)) - { - // Add the general message - JFactory::getApplication()->enqueueMessage($generalRemoteDatabaseMessage, 'warning'); - - JFactory::getApplication()->enqueueMessage( - JText::sprintf( - 'INSTL_DATABASE_HOST_IS_NOT_LOCALHOST_DELETE_FILE', - $remoteDbFile, - 'installation' - ), - 'error' - ); - - return false; - } - - if (JFactory::getSession()->get('remoteDbFileUnwritable', false) === true && !file_exists(JPATH_INSTALLATION . '/' . $remoteDbFile)) - { - // Add the general message - JFactory::getApplication()->enqueueMessage($generalRemoteDatabaseMessage, 'warning'); - - JFactory::getApplication()->enqueueMessage( - JText::sprintf( - 'INSTL_DATABASE_HOST_IS_NOT_LOCALHOST_CREATE_FILE', - $remoteDbFile, - 'installation' - ), - 'error' - ); - - return false; - } - - // All tests for this session passed set it to the session - JFactory::getSession()->set('remoteDbFileTestsPassed', true); + return false; } }