summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNathaniel Catchpole2016-02-03 15:15:58 +0900
committerNathaniel Catchpole2016-02-03 15:15:58 +0900
commit854898258d67abf385973ba9d9a71474362128e2 (patch)
tree6ff7b4b47ff74e84b13ab8b721164e9980fa60c7
parent18d44b50ff9318425bb8b2513e46acffa348aef7 (diff)
Issue #1232572 by deviantintegral, joachim, cweagans, kenorb, bleen, webflo, ceng, Elijah Lynn, sriharsha.uppuluri: Add a variable to disable fixing file permissions in drupal_install_fix_file()
-rw-r--r--core/modules/system/src/Tests/System/SitesDirectoryHardeningTest.php115
-rw-r--r--core/modules/system/system.install21
-rw-r--r--sites/example.settings.local.php12
3 files changed, 144 insertions, 4 deletions
diff --git a/core/modules/system/src/Tests/System/SitesDirectoryHardeningTest.php b/core/modules/system/src/Tests/System/SitesDirectoryHardeningTest.php
new file mode 100644
index 0000000..86ba0a2
--- /dev/null
+++ b/core/modules/system/src/Tests/System/SitesDirectoryHardeningTest.php
@@ -0,0 +1,115 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\system\Tests\System\SitesDirectoryHardeningTest.
+ */
+
+namespace Drupal\system\Tests\System;
+
+use Drupal\Component\Render\FormattableMarkup;
+use Drupal\Core\Site\Settings;
+use Drupal\Core\StringTranslation\StringTranslationTrait;
+use Drupal\simpletest\WebTestBase;
+
+/**
+ * Tests Drupal permissions hardening of /sites subdirectories.
+ *
+ * @group system
+ */
+class SitesDirectoryHardeningTest extends WebTestBase {
+ use StringTranslationTrait;
+
+ /**
+ * Tests the default behavior to restrict directory permissions is enforced.
+ *
+ * Checks both the the current sites directory and settings.php.
+ */
+ public function testSitesDirectoryHardening() {
+ $site_path = $this->kernel->getSitePath();
+ $settings_file = $this->settingsFile($site_path);
+
+ // First, we check based on what the initial install has set.
+ $this->assertTrue(drupal_verify_install_file($site_path, FILE_NOT_WRITABLE, 'dir'), new FormattableMarkup('Verified permissions for @file.', array('@file' => $site_path)));
+
+ // We intentionally don't check for settings.local.php as that file is
+ // not created by Drupal.
+ $this->assertTrue(drupal_verify_install_file($settings_file, FILE_EXIST|FILE_READABLE|FILE_NOT_WRITABLE), new FormattableMarkup('Verified permissions for @file.', array('@file' => $settings_file)));
+
+ $this->makeWritable($site_path);
+ $this->checkSystemRequirements();
+
+ $this->assertTrue(drupal_verify_install_file($site_path, FILE_NOT_WRITABLE, 'dir'), new FormattableMarkup('Verified permissions for @file after manual permissions change.', array('@file' => $site_path)));
+ $this->assertTrue(drupal_verify_install_file($settings_file, FILE_EXIST|FILE_READABLE|FILE_NOT_WRITABLE), new FormattableMarkup('Verified permissions for @file after manual permissions change.', array('@file' => $settings_file)));
+ }
+
+ /**
+ * Tests writable files remain writable when directory hardening is disabled.
+ */
+ public function testSitesDirectoryHardeningConfig() {
+ $site_path = $this->kernel->getSitePath();
+ $settings_file = $this->settingsFile($site_path);
+
+ // Disable permissions enforcement.
+ $settings = Settings::getAll();
+ $settings['skip_permissions_hardening'] = TRUE;
+ new Settings($settings);
+ $this->assertTrue(Settings::get('skip_permissions_hardening'), 'Able to set hardening to true');
+ $this->makeWritable($site_path);
+
+ // Manually trigger the requirements check.
+ $requirements = $this->checkSystemRequirements();
+ $this->assertEqual(REQUIREMENT_WARNING, $requirements['configuration_files']['severity'], 'Warning severity is properly set.');
+ $this->assertEqual($this->t('Protection disabled'), (string) $requirements['configuration_files']['description']['#context']['configuration_error_list']['#items'][0], 'Description is properly set.');
+
+ $this->assertTrue(is_writable($site_path), 'Site directory remains writable when automatically fixing permissions is disabled.');
+ $this->assertTrue(is_writable($settings_file), 'settings.php remains writable when automatically fixing permissions is disabled.');
+
+ // Re-enable permissions enforcement.
+ $settings = Settings::getAll();
+ $settings['skip_permissions_hardening'] = FALSE;
+ new Settings($settings);
+
+ // Manually trigger the requirements check.
+ $this->checkSystemRequirements();
+
+ $this->assertFalse(is_writable($site_path), 'Site directory is protected when automatically fixing permissions is enabled.');
+ $this->assertFalse(is_writable($settings_file), 'settings.php is protected when automatically fixing permissions is enabled.');
+ }
+
+ /**
+ * Checks system runtime requirements.
+ *
+ * @return array
+ * An array of system requirements.
+ */
+ protected function checkSystemRequirements() {
+ module_load_install('system');
+ return system_requirements('runtime');
+ }
+
+ /**
+ * Makes the given path and settings file writable.
+ *
+ * @param string $site_path
+ * The sites directory path, such as 'sites/default'.
+ */
+ protected function makeWritable($site_path) {
+ chmod($site_path, 0755);
+ chmod($this->settingsFile($site_path), 0644);
+ }
+
+ /**
+ * Returns the path to settings.php
+ *
+ * @param string $site_path
+ * The sites subdirectory path.
+ *
+ * @return string
+ * The path to settings.php.
+ */
+ protected function settingsFile($site_path) {
+ $settings_file = $site_path . '/settings.php';
+ return $settings_file;
+ }
+}
diff --git a/core/modules/system/system.install b/core/modules/system/system.install
index 133f57c..169921e 100644
--- a/core/modules/system/system.install
+++ b/core/modules/system/system.install
@@ -365,12 +365,25 @@ function system_requirements($phase) {
else {
$site_path = DrupalKernel::findSitePath(Request::createFromGlobals());
}
- if (!drupal_verify_install_file($site_path, FILE_NOT_WRITABLE, 'dir')) {
- $conf_errors[] = t("The directory %file is not protected from modifications and poses a security risk. You must change the directory's permissions to be non-writable.", array('%file' => $site_path));
+ // Allow system administrators to disable permissions hardening for the site
+ // directory. This allows additional files in the site directory to be
+ // updated when they are managed in a version control system.
+ if (Settings::get('skip_permissions_hardening')) {
+ $conf_errors[] = t('Protection disabled');
+ // If permissions hardening is disabled, then only show a warning for a
+ // writable file, as a reminder, rather than an error.
+ $file_protection_severity = REQUIREMENT_WARNING;
+ }
+ else {
+ // In normal operation, writable files or directories are an error.
+ $file_protection_severity = REQUIREMENT_ERROR;
+ if (!drupal_verify_install_file($site_path, FILE_NOT_WRITABLE, 'dir')) {
+ $conf_errors[] = t("The directory %file is not protected from modifications and poses a security risk. You must change the directory's permissions to be non-writable.", array('%file' => $site_path));
+ }
}
foreach (array('settings.php', 'settings.local.php', 'services.yml') as $conf_file) {
$full_path = $site_path . '/' . $conf_file;
- if (file_exists($full_path) && !drupal_verify_install_file($full_path, FILE_EXIST|FILE_READABLE|FILE_NOT_WRITABLE)) {
+ if (file_exists($full_path) && (Settings::get('skip_permissions_hardening') || !drupal_verify_install_file($full_path, FILE_EXIST|FILE_READABLE|FILE_NOT_WRITABLE))) {
$conf_errors[] = t("The file %file is not protected from modifications and poses a security risk. You must change the file's permissions to be non-writable.", array('%file' => $full_path));
}
}
@@ -393,7 +406,7 @@ function system_requirements($phase) {
}
$requirements['configuration_files'] = array(
'value' => t('Not protected'),
- 'severity' => REQUIREMENT_ERROR,
+ 'severity' => $file_protection_severity,
'description' => $description,
);
}
diff --git a/sites/example.settings.local.php b/sites/example.settings.local.php
index dfcc244..c3347ad 100644
--- a/sites/example.settings.local.php
+++ b/sites/example.settings.local.php
@@ -93,3 +93,15 @@ $settings['extension_discovery_scan_tests'] = TRUE;
* using these parameters in a request to rebuild.php.
*/
$settings['rebuild_access'] = TRUE;
+
+/**
+ * Skip file system permissions hardening.
+ *
+ * The system module will periodically check the permissions of your site's
+ * site directory to ensure that it is not writable by the website user. For
+ * sites that are managed with a version control system, this can cause problems
+ * when files in that directory such as settings.php are updated, because the
+ * user pulling in the changes won't have permissions to modify files in the
+ * directory.
+ */
+$settings['skip_permissions_hardening'] = TRUE;