/** * Test directory handling functions. */ function testFileCheckDirectoryHandling() { // A directory to operate on. $directory = file_default_scheme() . '://' . $this->randomMachineName() . '/' . $this->randomMachineName(); $this->assertFalse(is_dir($directory), 'Directory does not exist prior to testing.'); // Non-existent directory. $this->assertFalse(file_prepare_directory($directory, 0), 'Error reported for non-existing directory.', 'File'); // Make a directory. $this->assertTrue(file_prepare_directory($directory, FILE_CREATE_DIRECTORY), 'No error reported when creating a new directory.', 'File'); // Make sure directory actually exists. $this->assertTrue(is_dir($directory), 'Directory actually exists.', 'File'); if (substr(PHP_OS, 0, 3) != 'WIN') { // PHP on Windows doesn't support any kind of useful read-only mode for // directories. When executing a chmod() on a directory, PHP only sets the // read-only flag, which doesn't prevent files to actually be written // in the directory on any recent version of Windows. // Make directory read only. @drupal_chmod($directory, 0444); $this->assertFalse(file_prepare_directory($directory, 0), 'Error reported for a non-writeable directory.', 'File'); // Test directory permission modification. $this->settingsSet('file_chmod_directory', 0777); $this->assertTrue(file_prepare_directory($directory, FILE_MODIFY_PERMISSIONS), 'No error reported when making directory writeable.', 'File'); } // Test that the directory has the correct permissions. $this->assertDirectoryPermissions($directory, 0777, 'file_chmod_directory setting is respected.'); // Remove .htaccess file to then test that it gets re-created. @drupal_unlink(file_default_scheme() . '://.htaccess'); $this->assertFalse(is_file(file_default_scheme() . '://.htaccess'), 'Successfully removed the .htaccess file in the files directory.', 'File'); file_ensure_htaccess(); $this->assertTrue(is_file(file_default_scheme() . '://.htaccess'), 'Successfully re-created the .htaccess file in the files directory.', 'File'); // Verify contents of .htaccess file. $file = file_get_contents(file_default_scheme() . '://.htaccess'); $this->assertEqual($file, file_htaccess_lines(FALSE), 'The .htaccess file contains the proper content.', 'File'); }
/** * Check if PHP files written to the files directory can be executed. */ private function checkExecutablePHP($last_check = NULL) { global $base_url; $result = TRUE; $check_result_value = array(); $message = 'Security review test ' . date('Ymdhis'); $content = "<?php\necho '" . $message . "';"; $directory = Settings::get('file_public_path'); if (empty($directory)) { $directory = DrupalKernel::findSitePath(\Drupal::request()) . DIRECTORY_SEPARATOR . 'files'; } if (empty($directory)) { $directory = 'sites/default/files'; } $file = '/security_review_test.php'; if ($file_create = @fopen('./' . $directory . $file, 'w')) { $create_status = fwrite($file_create, $content); fclose($file_create); } try { $response = \Drupal::httpClient()->post($base_url . '/' . $directory . $file); if ($response->getStatusCode() == 200 && $response->getBody()->read(100) === $message) { $result = FALSE; $check_result_value[] = 'executable_php'; } } catch (\Exception $e) { $response = $e->getResponse(); } if (file_exists('./' . $directory . $file)) { @unlink('./' . $directory . $file); } // Check for presence of the .htaccess file and if the contents are correct. if (!file_exists($directory . '/.htaccess')) { $result = FALSE; $check_result_value[] = 'missing_htaccess'; } elseif (!function_exists('file_htaccess_lines')) { $result = FALSE; $check_result_value[] = 'outdated_core'; } else { $contents = file_get_contents($directory . '/.htaccess'); // Text from includes/file.inc. $expected = file_htaccess_lines(FALSE); if ($contents !== $expected) { $result = FALSE; $check_result_value[] = 'incorrect_htaccess'; } if (is_writable($directory . '/.htaccess')) { // Don't modify $result. $check_result_value[] = 'writable_htaccess'; } } return array('result' => $result, 'value' => $check_result_value); }