"Fossies" - the Fresh Open Source Software Archive

Member "drupal-8.9.9/core/lib/Drupal/Component/FileSecurity/FileSecurity.php" (18 Nov 2020, 4949 Bytes) of package /linux/www/drupal-8.9.9.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) PHP source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "FileSecurity.php" see the Fossies "Dox" file reference documentation.

    1 <?php
    2 
    3 namespace Drupal\Component\FileSecurity;
    4 
    5 /**
    6  * Provides file security functions.
    7  *
    8  * IMPORTANT: This file is duplicated at /composer/Plugin/VendorHardening.
    9  * If any change is made here, the same change should be made in the duplicate.
   10  * See https://www.drupal.org/project/drupal/issues/3079481
   11  */
   12 class FileSecurity {
   13 
   14   /**
   15    * Writes an .htaccess file in the given directory, if it doesn't exist.
   16    *
   17    * @param string $directory
   18    *   The directory.
   19    * @param bool $deny_public_access
   20    *   (optional) Set to FALSE to ensure an .htaccess file for an open and
   21    *   public directory. Default is TRUE.
   22    * @param bool $force
   23    *   (optional) Set to TRUE to force overwrite an existing file.
   24    *
   25    * @return bool
   26    *   TRUE if the file already exists or was created. FALSE otherwise.
   27    */
   28   public static function writeHtaccess($directory, $deny_public_access = TRUE, $force = FALSE) {
   29     return self::writeFile($directory, '.htaccess', self::htaccessLines($deny_public_access), $force);
   30   }
   31 
   32   /**
   33    * Returns the standard .htaccess lines that Drupal writes.
   34    *
   35    * @param bool $deny_public_access
   36    *   (optional) Set to FALSE to return the .htaccess lines for an open and
   37    *   public directory that allows Apache to serve files, but not execute code.
   38    *   The default is TRUE, which returns the .htaccess lines for a private and
   39    *   protected directory that Apache will deny all access to.
   40    *
   41    * @return string
   42    *   The desired contents of the .htaccess file.
   43    *
   44    * @see \Drupal\Component\FileSecurity\FileSecurity::writeHtaccess()
   45    */
   46   public static function htaccessLines($deny_public_access = TRUE) {
   47     $lines = static::htaccessPreventExecution();
   48 
   49     if ($deny_public_access) {
   50       $lines = static::denyPublicAccess() . "\n\n$lines";
   51     }
   52 
   53     return $lines;
   54   }
   55 
   56   /**
   57    * Returns htaccess directives to deny execution in a given directory.
   58    *
   59    * @return string
   60    *   Apache htaccess directives to prevent execution of files in a location.
   61    */
   62   protected static function htaccessPreventExecution() {
   63     return <<<EOF
   64 # Turn off all options we don't need.
   65 Options -Indexes -ExecCGI -Includes -MultiViews
   66 
   67 # Set the catch-all handler to prevent scripts from being executed.
   68 SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006
   69 <Files *>
   70   # Override the handler again if we're run later in the evaluation list.
   71   SetHandler Drupal_Security_Do_Not_Remove_See_SA_2013_003
   72 </Files>
   73 
   74 # If we know how to do it safely, disable the PHP engine entirely.
   75 <IfModule mod_php7.c>
   76   php_flag engine off
   77 </IfModule>
   78 EOF;
   79   }
   80 
   81   /**
   82    * Returns htaccess directives to block all access to a given directory.
   83    *
   84    * @return string
   85    *   Apache htaccess directives to block access to a location.
   86    */
   87   protected static function denyPublicAccess() {
   88     return <<<EOF
   89 # Deny all requests from Apache 2.4+.
   90 <IfModule mod_authz_core.c>
   91   Require all denied
   92 </IfModule>
   93 
   94 # Deny all requests from Apache 2.0-2.2.
   95 <IfModule !mod_authz_core.c>
   96   Deny from all
   97 </IfModule>
   98 EOF;
   99   }
  100 
  101   /**
  102    * Writes a web.config file in the given directory, if it doesn't exist.
  103    *
  104    * @param string $directory
  105    *   The directory.
  106    * @param bool $force
  107    *   (optional) Set to TRUE to force overwrite an existing file.
  108    *
  109    * @return bool
  110    *   TRUE if the file already exists or was created. FALSE otherwise.
  111    */
  112   public static function writeWebConfig($directory, $force = FALSE) {
  113     return self::writeFile($directory, 'web.config', self::webConfigLines(), $force);
  114   }
  115 
  116   /**
  117    * Returns the standard web.config lines for security.
  118    *
  119    * @return string
  120    *   The contents of the web.config file.
  121    */
  122   public static function webConfigLines() {
  123     return <<<EOT
  124 <configuration>
  125   <system.webServer>
  126     <authorization>
  127       <deny users="*">
  128     </authorization>
  129   </system.webServer>
  130 </configuration>
  131 EOT;
  132   }
  133 
  134   /**
  135    * Writes the contents to the file in the given directory.
  136    *
  137    * @param string $directory
  138    *   The directory to write to.
  139    * @param string $filename
  140    *   The file name.
  141    * @param string $contents
  142    *   The file contents.
  143    * @param bool $force
  144    *   TRUE if we should force the write over an existing file.
  145    *
  146    * @return bool
  147    *   TRUE if writing the file was successful.
  148    */
  149   protected static function writeFile($directory, $filename, $contents, $force) {
  150     $file_path = $directory . DIRECTORY_SEPARATOR . $filename;
  151     // Don't overwrite if the file exists unless forced.
  152     if (file_exists($file_path) && !$force) {
  153       return TRUE;
  154     }
  155     // Writing the file can fail if:
  156     // - concurrent requests are both trying to write at the same time.
  157     // - $directory does not exist or is not writable.
  158     // Testing for these conditions introduces windows for concurrency issues to
  159     // occur.
  160     if (@file_put_contents($file_path, $contents)) {
  161       return @chmod($file_path, 0444);
  162     }
  163     return FALSE;
  164   }
  165 
  166 }