diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc index 846146a..f6cd6a7 100644 --- a/core/includes/bootstrap.inc +++ b/core/includes/bootstrap.inc @@ -596,7 +596,7 @@ function drupal_settings_initialize() { global $base_url, $base_path, $base_root, $script_path; // Export the following settings.php variables to the global namespace - global $databases, $cookie_domain, $conf, $installed_profile, $update_free_access, $db_url, $db_prefix, $drupal_hash_salt, $is_https, $base_secure_url, $base_insecure_url, $config_directory_name, $config_signature_key; + global $databases, $cookie_domain, $conf, $installed_profile, $update_free_access, $db_url, $db_prefix, $drupal_hash_salt, $is_https, $base_secure_url, $base_insecure_url, $config_directory_name; $conf = array(); if (file_exists(DRUPAL_ROOT . '/' . conf_path() . '/settings.php')) { diff --git a/core/includes/config.inc b/core/includes/config.inc index cb81acc..5e6fa00 100644 --- a/core/includes/config.inc +++ b/core/includes/config.inc @@ -71,7 +71,7 @@ function config_install_default_config($module) { * @return * An array of file names under a branch. */ -function config_get_signed_file_storage_names_with_prefix($prefix = '') { +function config_get_files_with_prefix($prefix = '') { $files = glob(config_get_config_directory() . '/' . $prefix . '*.xml'); $clean_name = function ($value) { return basename($value, '.xml'); @@ -80,23 +80,6 @@ function config_get_signed_file_storage_names_with_prefix($prefix = '') { } /** - * Generates a hash of a config file's contents using our encryption key. - * - * @param $data - * The contents of a configuration file. - * - * @return - * A hash of the data. - */ -function config_sign_data($data) { - // The configuration key is loaded from settings.php and imported into the global namespace - global $config_signature_key; - - // SHA-512 is both secure and very fast on 64 bit CPUs. - return hash_hmac('sha512', $data, $config_signature_key); -} - -/** * @todo * * @param $prefix diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc index 76ce3e6..31ef052 100644 --- a/core/includes/install.core.inc +++ b/core/includes/install.core.inc @@ -1002,11 +1002,6 @@ function install_settings_form_submit($form, &$form_state) { 'required' => TRUE, ); - $settings['config_signature_key'] = array( - 'value' => drupal_hash_base64(drupal_random_bytes(55)), - 'required' => TRUE, - ); - // This duplicates drupal_get_token() because that function can't work yet. // Wondering if it makes sense to move this later in the process, but its // nice having all the settings stuff here. @@ -1016,7 +1011,7 @@ function install_settings_form_submit($form, &$form_state) { // already has the db stuff in it, and right now in that case your // config directory never gets created. So this needs to be moved elsewhere. $settings['config_directory_name'] = array( - 'value' => 'config_' . drupal_hmac_base64('', session_id() . $settings['config_signature_key']['value'] . $settings['drupal_hash_salt']['value']), + 'value' => 'config_' . drupal_hmac_base64('', session_id() . $settings['drupal_hash_salt']['value']), 'required' => TRUE, ); diff --git a/core/includes/install.inc b/core/includes/install.inc index 283e31c..f278a6a 100644 --- a/core/includes/install.inc +++ b/core/includes/install.inc @@ -1,7 +1,7 @@ delete(); + $file_storage->delete(); } } diff --git a/core/lib/Drupal/Core/Config/ConfigFileStorageSignatureException.php b/core/lib/Drupal/Core/Config/ConfigFileStorageSignatureException.php deleted file mode 100644 index 65c5c59..0000000 --- a/core/lib/Drupal/Core/Config/ConfigFileStorageSignatureException.php +++ /dev/null @@ -1,10 +0,0 @@ -signedFile)) { - $this->signedFile = new SignedFileStorage($this->name); + protected function fileStorage() { + if (!isset($this->fileStorage)) { + $this->fileStorage = new FileStorage($this->name); } - return $this->signedFile; + return $this->fileStorage; } /** @@ -50,7 +50,7 @@ abstract class DrupalConfigVerifiedStorage implements DrupalConfigVerifiedStorag * Implements DrupalConfigVerifiedStorageInterface::deleteFile(). */ public function deleteFile() { - return $this->signedFileStorage()->delete(); + return $this->fileStorage()->delete(); } /** @@ -67,7 +67,7 @@ abstract class DrupalConfigVerifiedStorage implements DrupalConfigVerifiedStorag * @todo */ public function readFromFile() { - return $this->signedFileStorage()->read($this->name); + return $this->fileStorage()->read($this->name); } /** @@ -89,7 +89,7 @@ abstract class DrupalConfigVerifiedStorage implements DrupalConfigVerifiedStorag * Implements DrupalConfigVerifiedStorageInterface::writeToFile(). */ public function writeToFile($data) { - return $this->signedFileStorage()->write($data); + return $this->fileStorage()->write($data); } /** diff --git a/core/lib/Drupal/Core/Config/DrupalConfigVerifiedStorageInterface.php b/core/lib/Drupal/Core/Config/DrupalConfigVerifiedStorageInterface.php index 47a5ddb..8048e35 100644 --- a/core/lib/Drupal/Core/Config/DrupalConfigVerifiedStorageInterface.php +++ b/core/lib/Drupal/Core/Config/DrupalConfigVerifiedStorageInterface.php @@ -6,7 +6,7 @@ namespace Drupal\Core\Config; * Defines an interface for verified storage manipulation. * * This class allows reading and writing configuration data from/to the - * verified storage and copying to/from the signed file storing the same data. + * verified storage and copying to/from the file storing the same data. */ interface DrupalConfigVerifiedStorageInterface { diff --git a/core/lib/Drupal/Core/Config/FileStorage.php b/core/lib/Drupal/Core/Config/FileStorage.php new file mode 100644 index 0000000..77b8db5 --- /dev/null +++ b/core/lib/Drupal/Core/Config/FileStorage.php @@ -0,0 +1,96 @@ +name = $name; + } + + /** + * Reads and returns a file. + * + * @return + * The data of the file. + * + * @throws + * Exception + */ + protected function readData() { + $data = file_get_contents($this->getFilePath()); + if ($data === FALSE) { + throw new \Exception('Read file is invalid.'); + } + return $data; + } + + /** + * Checks whether the XML configuration file already exists on disk. + * + * @return + * @todo + */ + protected function exists() { + return file_exists($this->getFilePath()); + } + + /** + * Returns the path to the XML configuration file. + * + * @return + * @todo + */ + public function getFilePath() { + return config_get_config_directory() . '/' . $this->name . '.xml'; + } + + /** + * Writes the contents of the configuration file to disk. + * + * @param $data + * The data to be written to the file. + * + * @throws + * Exception + */ + public function write($data) { + if (!file_put_contents($this->getFilePath(), $data)) { + throw new \Exception('Failed to write configuration file: ' . $this->getFilePath()); + } + } + + /** + * Returns the contents of the configuration file. + * + * @return + * @todo + */ + public function read() { + if ($this->exists()) { + $data = $this->readData(); + return $data; + } + return FALSE; + } + + /** + * Deletes a configuration file. + */ + public function delete() { + // Needs error handling and etc. + @drupal_unlink($this->getFilePath()); + } +} diff --git a/core/lib/Drupal/Core/Config/SignedFileStorage.php b/core/lib/Drupal/Core/Config/SignedFileStorage.php deleted file mode 100644 index c669029..0000000 --- a/core/lib/Drupal/Core/Config/SignedFileStorage.php +++ /dev/null @@ -1,143 +0,0 @@ -name = $name; - } - - /** - * Reads and returns a signed file and its signature. - * - * @return - * An array with "signature" and "data" keys. - * - * @throws - * Exception - */ - protected function readWithSignature() { - $content = file_get_contents($this->getFilePath()); - if ($content === FALSE) { - throw new \Exception('Read file is invalid.'); - } - $signature = file_get_contents($this->getFilePath() . '.sig'); - if ($signature === FALSE) { - throw new \Exception('Signature file is invalid.'); - } - return array('data' => $content, 'signature' => $signature); - } - - /** - * Checks whether the XML configuration file already exists on disk. - * - * @return - * @todo - */ - protected function exists() { - return file_exists($this->getFilePath()); - } - - /** - * Returns the path to the XML configuration file. - * - * @return - * @todo - */ - public function getFilePath() { - return config_get_config_directory() . '/' . $this->name . '.xml'; - } - - /** - * Recreates the signature for the file. - */ - public function resign() { - if ($this->exists()) { - $parts = $this->readWithSignature(); - $this->write($parts['data']); - } - } - - /** - * Cryptographically verifies the integrity of the configuration file. - * - * @param $contentOnSuccess - * Whether or not to return the contents of the verified configuration file. - * - * @return mixed - * If $contentOnSuccess was TRUE, returns the contents of the verified - * configuration file; otherwise returns TRUE on success. Always returns - * FALSE if the configuration file was not successfully verified. - */ - public function verify($contentOnSuccess = FALSE) { - if ($this->exists()) { - $split = $this->readWithSignature(); - $expected_signature = config_sign_data($split['data']); - if ($expected_signature === $split['signature']) { - if ($contentOnSuccess) { - return $split['data']; - } - return TRUE; - } - } - return FALSE; - } - - /** - * Writes the contents of the configuration file to disk. - * - * @param $data - * The data to be written to the file. - * - * @throws - * Exception - */ - public function write($data) { - $signature = config_sign_data($data); - if (!file_put_contents($this->getFilePath(), $data)) { - throw new \Exception('Failed to write configuration file: ' . $this->getFilePath()); - } - if (!file_put_contents($this->getFilePath() . '.sig', $signature)) { - throw new \Exception('Failed to write signature file: ' . $this->getFilePath()); - } - } - - /** - * Returns the contents of the configuration file. - * - * @return - * @todo - */ - public function read() { - if ($this->exists()) { - $verification = $this->verify(TRUE); - if ($verification === FALSE) { - throw new \Exception('Invalid signature in file header.'); - } - return $verification; - } - } - - /** - * Deletes a configuration file. - */ - public function delete() { - // Needs error handling and etc. - @drupal_unlink($this->getFilePath()); - @drupal_unlink($this->getFilePath() . '.sig'); - } -} diff --git a/core/modules/config/config.test b/core/modules/config/config.test index a164108..c111aba 100644 --- a/core/modules/config/config.test +++ b/core/modules/config/config.test @@ -5,14 +5,12 @@ * Tests for the Configuration module. */ -use Drupal\Core\Config\SignedFileStorage; +use Drupal\Core\Config\FileStorage; /** * Tests the secure file writer. */ class ConfigFileSecurityTestCase extends DrupalWebTestCase { - protected $profile = 'testing'; - protected $filename = 'foo.bar'; protected $testContent = 'Good morning, Denver!'; @@ -26,26 +24,10 @@ class ConfigFileSecurityTestCase extends DrupalWebTestCase { } /** - * Tests that a file written by this system has a valid signature. - */ - function testFileVerify() { - $file = new SignedFileStorage($this->filename); - $file->write($this->testContent); - - $this->assertTrue($file->verify(), 'A file verifies after being written.'); - - unset($file); - - // Load the file again, so that there is no stale data from the old object. - $file = new SignedFileStorage($this->filename); - $this->assertTrue($file->verify(), 'A file verifies after being written and reloaded.'); - } - - /** * Tests that a file written by this system can be successfully read back. */ function testFilePersist() { - $file = new SignedFileStorage($this->filename); + $file = new FileStorage($this->filename); $file->write($this->testContent); unset($file); @@ -54,7 +36,7 @@ class ConfigFileSecurityTestCase extends DrupalWebTestCase { // Note that if any other exception is thrown, we let the test system // handle catching and reporting it. try { - $file = new SignedFileStorage($this->filename); + $file = new FileStorage($this->filename); $saved_content = $file->read(); $this->assertEqual($saved_content, $this->testContent, 'A file can be read back successfully.'); @@ -63,35 +45,12 @@ class ConfigFileSecurityTestCase extends DrupalWebTestCase { $this->fail('File failed verification when being read.'); } } - - /** - * Tests that a file fails validation if it's been monkeyed with. - */ - function testFileNotVerify() { - $file = new SignedFileStorage($this->filename); - $file->write($this->testContent); - - // Manually overwrite the body of the secure file. Note that we skip the - // first line, which is reserved for the signature and such, to overwrite - // just the payload. - $raw_file = new SplFileObject($file->getFilePath(), 'a+'); - $raw_file->fwrite('Good morning, Detroit!'); - $raw_file->fflush(); - unset($raw_file); - - unset($file); - - $file = new SignedFileStorage($this->filename); - $this->assertFalse($file->verify(), 'Corrupted file does not verify.'); - } } /** * Tests reading and writing file contents. */ class ConfigFileContentTestCase extends DrupalWebTestCase { - protected $profile = 'testing'; - protected $fileExtension = 'xml'; public static function getInfo() { @@ -238,22 +197,22 @@ class ConfigFileContentTestCase extends DrupalWebTestCase { // Get file listing for all files starting with 'foo'. Should return // two elements. - $files = config_get_signed_file_storage_names_with_prefix('foo'); + $files = config_get_files_with_prefix('foo'); $this->assertEqual(count($files), 2, 'Two files listed with the prefix \'foo\'.'); // Get file listing for all files starting with 'biff'. Should return // one element. - $files = config_get_signed_file_storage_names_with_prefix('biff'); + $files = config_get_files_with_prefix('biff'); $this->assertEqual(count($files), 1, 'One file listed with the prefix \'biff\'.'); // Get file listing for all files starting with 'foo.bar'. Should return // one element. - $files = config_get_signed_file_storage_names_with_prefix('foo.bar'); + $files = config_get_files_with_prefix('foo.bar'); $this->assertEqual(count($files), 1, 'One file listed with the prefix \'foo.bar\'.'); // Get file listing for all files starting with 'bar'. Should return // an empty array. - $files = config_get_signed_file_storage_names_with_prefix('bar'); + $files = config_get_files_with_prefix('bar'); $this->assertEqual($files, array(), 'No files listed with the prefix \'bar\'.'); // Delete the configuration. diff --git a/core/modules/simpletest/drupal_web_test_case.php b/core/modules/simpletest/drupal_web_test_case.php index 23fa526..3b353c4 100644 --- a/core/modules/simpletest/drupal_web_test_case.php +++ b/core/modules/simpletest/drupal_web_test_case.php @@ -1344,7 +1344,6 @@ class DrupalWebTestCase extends DrupalTestCase { $this->originalLanguage = $language_interface; $this->originalLanguageDefault = variable_get('language_default'); $this->originalConfigDirectory = $GLOBALS['config_directory_name']; - $this->originalConfigSignatureKey = $GLOBALS['config_signature_key']; $this->originalFileDirectory = variable_get('file_public_path', conf_path() . '/files'); $this->originalProfile = drupal_get_profile(); $this->originalUser = $user; @@ -1377,7 +1376,6 @@ class DrupalWebTestCase extends DrupalTestCase { $GLOBALS['config_directory_name'] = 'simpletest/' . substr($this->databasePrefix, 10) . '/config'; $this->configFileDirectory = $this->originalFileDirectory . '/' . $GLOBALS['config_directory_name']; file_prepare_directory($this->configFileDirectory, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS); - $GLOBALS['config_signature_key'] = drupal_hash_base64(drupal_random_bytes(55)); // Log fatal errors. ini_set('log_errors', 1); @@ -1639,7 +1637,6 @@ class DrupalWebTestCase extends DrupalTestCase { // Reset configuration globals. $GLOBALS['config_directory_name'] = $this->originalConfigDirectory; - $GLOBALS['config_signature_key'] = $this->originalConfigSignatureKey; // Reset language. $language_interface = $this->originalLanguage; diff --git a/sites/default/default.settings.php b/sites/default/default.settings.php index 4f3fab8..a6c38e4 100755 --- a/sites/default/default.settings.php +++ b/sites/default/default.settings.php @@ -252,13 +252,6 @@ $drupal_hash_salt = ''; $config_directory_name = ''; /** - * Configuration signature key. - * - * Drupal configuration files are signed using this key. - */ -$config_signature_key = ''; - -/** * Base URL (optional). * * If Drupal is generating incorrect URLs on your site, which could