class FileSecurity

Same name in this branch
  1. 9 composer/Plugin/VendorHardening/FileSecurity.php \Drupal\Composer\Plugin\VendorHardening\FileSecurity
Same name and namespace in other branches
  1. 8.9.x composer/Plugin/VendorHardening/FileSecurity.php \Drupal\Composer\Plugin\VendorHardening\FileSecurity
  2. 8.9.x core/lib/Drupal/Component/FileSecurity/FileSecurity.php \Drupal\Component\FileSecurity\FileSecurity
  3. 10 composer/Plugin/VendorHardening/FileSecurity.php \Drupal\Composer\Plugin\VendorHardening\FileSecurity
  4. 10 core/lib/Drupal/Component/FileSecurity/FileSecurity.php \Drupal\Component\FileSecurity\FileSecurity
  5. 11.x composer/Plugin/VendorHardening/FileSecurity.php \Drupal\Composer\Plugin\VendorHardening\FileSecurity
  6. 11.x core/lib/Drupal/Component/FileSecurity/FileSecurity.php \Drupal\Component\FileSecurity\FileSecurity

Provides file security functions.

IMPORTANT: This file is duplicated at /composer/Plugin/VendorHardening. If any change is made here, the same change should be made in the duplicate. See https://www.drupal.org/project/drupal/issues/3079481

Hierarchy

Expanded class hierarchy of FileSecurity

9 files declare their use of FileSecurity
Composer.php in core/lib/Drupal/Core/Composer/Composer.php
DirectoryTest.php in core/tests/Drupal/KernelTests/Core/File/DirectoryTest.php
FileSaveHtaccessLoggingTest.php in core/modules/system/tests/src/Functional/File/FileSaveHtaccessLoggingTest.php
FileSecurityTest.php in core/tests/Drupal/Tests/Component/FileSecurity/FileSecurityTest.php
FileStorage.php in core/lib/Drupal/Core/Config/FileStorage.php

... See full list

File

core/lib/Drupal/Component/FileSecurity/FileSecurity.php, line 12

Namespace

Drupal\Component\FileSecurity
View source
class FileSecurity {
    
    /**
     * Writes an .htaccess file in the given directory, if it doesn't exist.
     *
     * @param string $directory
     *   The directory.
     * @param bool $deny_public_access
     *   (optional) Set to FALSE to ensure an .htaccess file for an open and
     *   public directory. Default is TRUE.
     * @param bool $force
     *   (optional) Set to TRUE to force overwrite an existing file.
     *
     * @return bool
     *   TRUE if the file already exists or was created. FALSE otherwise.
     */
    public static function writeHtaccess($directory, $deny_public_access = TRUE, $force = FALSE) {
        return self::writeFile($directory, '.htaccess', self::htaccessLines($deny_public_access), $force);
    }
    
    /**
     * Returns the standard .htaccess lines that Drupal writes.
     *
     * @param bool $deny_public_access
     *   (optional) Set to FALSE to return the .htaccess lines for an open and
     *   public directory that allows Apache to serve files, but not execute code.
     *   The default is TRUE, which returns the .htaccess lines for a private and
     *   protected directory that Apache will deny all access to.
     *
     * @return string
     *   The desired contents of the .htaccess file.
     *
     * @see \Drupal\Component\FileSecurity\FileSecurity::writeHtaccess()
     */
    public static function htaccessLines($deny_public_access = TRUE) {
        $lines = static::htaccessPreventExecution();
        if ($deny_public_access) {
            $lines = static::denyPublicAccess() . "\n\n{$lines}";
        }
        return $lines;
    }
    
    /**
     * Returns htaccess directives to deny execution in a given directory.
     *
     * @return string
     *   Apache htaccess directives to prevent execution of files in a location.
     */
    protected static function htaccessPreventExecution() {
        return <<<EOF
# Turn off all options we don't need.
Options -Indexes -ExecCGI -Includes -MultiViews

# Set the catch-all handler to prevent scripts from being executed.
SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006
<Files *>
  # Override the handler again if we're run later in the evaluation list.
  SetHandler Drupal_Security_Do_Not_Remove_See_SA_2013_003
</Files>

# If we know how to do it safely, disable the PHP engine entirely.
<IfModule mod_php7.c>
  php_flag engine off
</IfModule>
<IfModule mod_php.c>
  php_flag engine off
</IfModule>
EOF;
    }
    
    /**
     * Returns htaccess directives to block all access to a given directory.
     *
     * @return string
     *   Apache htaccess directives to block access to a location.
     */
    protected static function denyPublicAccess() {
        return <<<EOF
# Deny all requests from Apache 2.4+.
<IfModule mod_authz_core.c>
  Require all denied
</IfModule>

# Deny all requests from Apache 2.0-2.2.
<IfModule !mod_authz_core.c>
  Deny from all
</IfModule>
EOF;
    }
    
    /**
     * Writes a web.config file in the given directory, if it doesn't exist.
     *
     * @param string $directory
     *   The directory.
     * @param bool $force
     *   (optional) Set to TRUE to force overwrite an existing file.
     *
     * @return bool
     *   TRUE if the file already exists or was created. FALSE otherwise.
     */
    public static function writeWebConfig($directory, $force = FALSE) {
        return self::writeFile($directory, 'web.config', self::webConfigLines(), $force);
    }
    
    /**
     * Returns the standard web.config lines for security.
     *
     * @return string
     *   The contents of the web.config file.
     */
    public static function webConfigLines() {
        return <<<EOT
<configuration>
  <system.webServer>
    <authorization>
      <deny users="*">
    </authorization>
  </system.webServer>
</configuration>
EOT;
    }
    
    /**
     * Writes the contents to the file in the given directory.
     *
     * @param string $directory
     *   The directory to write to.
     * @param string $filename
     *   The file name.
     * @param string $contents
     *   The file contents.
     * @param bool $force
     *   TRUE if we should force the write over an existing file.
     *
     * @return bool
     *   TRUE if writing the file was successful.
     */
    protected static function writeFile($directory, $filename, $contents, $force) {
        $file_path = $directory . DIRECTORY_SEPARATOR . $filename;
        // Don't overwrite if the file exists unless forced.
        if (file_exists($file_path) && !$force) {
            return TRUE;
        }
        // Writing the file can fail if:
        // - concurrent requests are both trying to write at the same time.
        // - $directory does not exist or is not writable.
        // Testing for these conditions introduces windows for concurrency issues to
        // occur.
        if (@file_put_contents($file_path, $contents)) {
            return @chmod($file_path, 0444);
        }
        return FALSE;
    }

}

Members

Title Sort descending Modifiers Object type Summary
FileSecurity::denyPublicAccess protected static function Returns htaccess directives to block all access to a given directory.
FileSecurity::htaccessLines public static function Returns the standard .htaccess lines that Drupal writes.
FileSecurity::htaccessPreventExecution protected static function Returns htaccess directives to deny execution in a given directory.
FileSecurity::webConfigLines public static function Returns the standard web.config lines for security.
FileSecurity::writeFile protected static function Writes the contents to the file in the given directory.
FileSecurity::writeHtaccess public static function Writes an .htaccess file in the given directory, if it doesn&#039;t exist.
FileSecurity::writeWebConfig public static function Writes a web.config file in the given directory, if it doesn&#039;t exist.

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.