Updated Drupal to 8.6. This goes with the following updates because it's possible...
[yaffs-website] / web / core / lib / Drupal / Component / PhpStorage / MTimeProtectedFileStorage.php
1 <?php
2
3 namespace Drupal\Component\PhpStorage;
4
5 /**
6  * Stores PHP code in files with securely hashed names.
7  *
8  * The goal of this class is to ensure that if a PHP file is replaced with
9  * an untrusted one, it does not get loaded. Since mtime granularity is 1
10  * second, we cannot prevent an attack that happens within one second of the
11  * initial save(). However, it is very unlikely for an attacker exploiting an
12  * upload or file write vulnerability to also know when a legitimate file is
13  * being saved, discover its hash, undo its file permissions, and override the
14  * file with an upload all within a single second. Being able to accomplish
15  * that would indicate a site very likely vulnerable to many other attack
16  * vectors.
17  *
18  * Each file is stored in its own unique containing directory. The hash is
19  * based on the virtual file name, the containing directory's mtime, and a
20  * cryptographically hard to guess secret string. Thus, even if the hashed file
21  * name is discovered and replaced by an untrusted file (e.g., via a
22  * move_uploaded_file() invocation by a script that performs insufficient
23  * validation), the directory's mtime gets updated in the process, invalidating
24  * the hash and preventing the untrusted file from getting loaded. Also, the
25  * file mtime will be checked providing security against overwriting in-place,
26  * at the cost of an additional system call for every load() and exists().
27  *
28  * The containing directory is created with the same name as the virtual file
29  * name (slashes replaced with hashmarks) to assist with debugging, since the
30  * file itself is stored with a name that's meaningless to humans.
31  */
32 class MTimeProtectedFileStorage extends MTimeProtectedFastFileStorage {
33
34   /**
35    * {@inheritdoc}
36    */
37   public function load($name) {
38     if (($filename = $this->checkFile($name)) !== FALSE) {
39       // Inline parent::load() to avoid an expensive getFullPath() call.
40       return (@include_once $filename) !== FALSE;
41     }
42     return FALSE;
43   }
44
45   /**
46    * {@inheritdoc}
47    */
48   public function exists($name) {
49     return $this->checkFile($name) !== FALSE;
50   }
51
52   /**
53    * Determines whether a protected file exists and sets the filename too.
54    *
55    * @param string $name
56    *   The virtual file name. Can be a relative path.
57    *
58    * @return string|false
59    *   The full path where the file is if it is valid, FALSE otherwise.
60    */
61   protected function checkFile($name) {
62     $filename = $this->getFullPath($name, $directory, $directory_mtime);
63     return file_exists($filename) && filemtime($filename) <= $directory_mtime ? $filename : FALSE;
64   }
65
66   /**
67    * {@inheritdoc}
68    */
69   public function getPath($name) {
70     return $this->checkFile($name);
71   }
72
73 }