| <?php |
|
|
| |
| |
| |
| |
| |
| |
|
|
| namespace Piwik\Plugins\Installation; |
|
|
| use Piwik\Container\StaticContainer; |
| use Piwik\Filesystem; |
| use Piwik\SettingsServer; |
| use Piwik\Config; |
|
|
| class ServerFilesGenerator |
| { |
| public static function createFilesForSecurity() |
| { |
| self::createHtAccessFiles(); |
| self::createWebConfigFiles(); |
| self::createWebRootFiles(); |
| } |
|
|
| |
| |
| |
| |
| public static function createHtAccessFiles() |
| { |
| $denyAll = self::getDenyAllHtaccessContent(); |
| $allow = self::getAllowHtaccessContent(); |
|
|
| $allowAny = |
| "# Allow any file in this directory\n" . |
| "<Files \"*\">\n" . |
| "\t" . $allow . "\n" . |
| "</Files>\n"; |
|
|
| $staticFileExtensions = ['gif', 'ico', 'jpg', 'png', 'svg', 'js', 'css', 'htm', 'html', 'mp3', 'mp4', 'wav', 'ogg', 'avi', 'ttf', 'eot', 'woff', 'woff2']; |
| $allowVueSourceMaps = !empty(Config::getInstance()->Development['allow_vue_sourcemaps']); |
| if ($allowVueSourceMaps) { |
| $staticFileExtensions[] = 'map'; |
| } |
| $staticFileExtensionsPattern = implode('|', $staticFileExtensions); |
|
|
| $allowStaticAssets = |
| "# Serve HTML files as text/html mime type - Note: requires mod_mime apache module!\n" . |
| "<IfModule mod_mime.c>\n" . |
| " AddHandler text/html .html\n" . |
| " AddHandler text/html .htm\n" . |
| "</IfModule>\n\n" . |
|
|
| "# Allow to serve static files which are safe\n" . |
| "<Files ~ \"\\.(" . $staticFileExtensionsPattern . ")$\">\n" . |
| $allow . "\n" . |
| "</Files>\n"; |
|
|
| $noCachePreview = " |
| # do not cache preview container files |
| <Files ~ \"^container_.*_preview\.js$\"> |
| <IfModule mod_headers.c> |
| Header set Cache-Control \"Cache-Control: private, no-cache, no-store\" |
| </IfModule> |
| </Files>"; |
|
|
| $allowManifestFile = |
| "# Allow to serve manifest.json\n" . |
| "<Files \"manifest.json\">\n" . |
| $allow . "\n" . |
| "</Files>\n"; |
|
|
| $directoriesToProtect = array( |
| '/js' => $allowAny . $noCachePreview, |
| '/libs' => $denyAll . $allowStaticAssets, |
| '/vendor' => $denyAll . $allowStaticAssets, |
| '/plugins' => $denyAll . $allowStaticAssets . $allowManifestFile, |
| '/misc' => $denyAll . $allowStaticAssets, |
| '/node_modules' => $denyAll . $allowStaticAssets, |
| ); |
| foreach ($directoriesToProtect as $directoryToProtect => $content) { |
| self::createHtAccess(PIWIK_INCLUDE_PATH . $directoryToProtect, $overwrite = true, $content); |
| } |
|
|
| |
| $directoriesToProtect = array( |
| PIWIK_USER_PATH . '/config' => $denyAll, |
| PIWIK_INCLUDE_PATH . '/core' => $denyAll, |
| PIWIK_INCLUDE_PATH . '/lang' => $denyAll, |
| StaticContainer::get('path.tmp') => $denyAll, |
| ); |
|
|
| if (!empty($GLOBALS['CONFIG_INI_PATH_RESOLVER']) && is_callable($GLOBALS['CONFIG_INI_PATH_RESOLVER'])) { |
| $file = call_user_func($GLOBALS['CONFIG_INI_PATH_RESOLVER']); |
| $directoriesToProtect[dirname($file)] = $denyAll; |
| } |
|
|
| $gitDir = PIWIK_INCLUDE_PATH . '/.git'; |
| if (is_dir($gitDir) && is_writable($gitDir)) { |
| $directoriesToProtect[$gitDir] = $denyAll; |
| } |
|
|
| foreach ($directoriesToProtect as $directoryToProtect => $content) { |
| self::createHtAccess($directoryToProtect, $overwrite = true, $content); |
| } |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| protected static function createHtAccess($path, $overwrite, $content) |
| { |
| $file = $path . '/.htaccess'; |
|
|
| $content = "# This file is auto generated by Matomo, do not edit directly\n# Please report any issue or improvement directly to the Matomo team.\n\n" . $content; |
| if ($overwrite || !file_exists($file)) { |
| @file_put_contents($file, $content, LOCK_EX); |
| } |
| } |
|
|
| |
| |
| |
| |
| |
| protected static function createWebConfigFiles() |
| { |
| if (!SettingsServer::isIIS()) { |
| return; |
| } |
| @file_put_contents( |
| PIWIK_INCLUDE_PATH . '/web.config', |
| '<?xml version="1.0" encoding="UTF-8"?> |
| <configuration> |
| <system.webServer> |
| <security> |
| <requestFiltering> |
| <hiddenSegments> |
| <add segment="config" /> |
| <add segment="core" /> |
| <add segment="lang" /> |
| <add segment="tmp" /> |
| </hiddenSegments> |
| <fileExtensions> |
| <add fileExtension=".tpl" allowed="false" /> |
| <add fileExtension=".twig" allowed="false" /> |
| <add fileExtension=".php4" allowed="false" /> |
| <add fileExtension=".php5" allowed="false" /> |
| <add fileExtension=".inc" allowed="false" /> |
| <add fileExtension=".in" allowed="false" /> |
| <add fileExtension=".csv" allowed="false" /> |
| <add fileExtension=".pdf" allowed="false" /> |
| <add fileExtension=".log" allowed="false" /> |
| </fileExtensions> |
| </requestFiltering> |
| </security> |
| <directoryBrowse enabled="false" /> |
| <defaultDocument> |
| <files> |
| <remove value="index.php" /> |
| <add value="index.php" /> |
| </files> |
| </defaultDocument> |
| <staticContent> |
| <remove fileExtension=".svg" /> |
| <mimeMap fileExtension=".svg" mimeType="image/svg+xml" /> |
| <remove fileExtension=".woff" /> |
| <mimeMap fileExtension=".woff" mimeType="application/font-woff" /> |
| </staticContent> |
| </system.webServer> |
| </configuration>' |
| ); |
|
|
| $additionForPlugins = ' |
| <alwaysAllowedUrls> |
| <add url="/plugins/HeatmapSessionRecording/configs.php" /> |
| </alwaysAllowedUrls>'; |
|
|
| $additionForMisc = ' |
| <alwaysAllowedUrls> |
| <add url="/misc/cron/archive.php" /> |
| </alwaysAllowedUrls>'; |
|
|
| |
| $directoriesToProtect = array( |
| '/libs' => '', |
| '/vendor' => '', |
| '/plugins' => $additionForPlugins, |
| '/node_modules' => '', |
| '/misc' => $additionForMisc, |
| ); |
|
|
| foreach ($directoriesToProtect as $directoryToProtect => $additions) { |
| @file_put_contents( |
| PIWIK_INCLUDE_PATH . $directoryToProtect . '/web.config', |
| '<?xml version="1.0" encoding="UTF-8"?> |
| <configuration> |
| <system.webServer> |
| <security> |
| <requestFiltering> |
| <denyUrlSequences> |
| <add sequence=".php" /> |
| </denyUrlSequences>' . $additions . ' |
| </requestFiltering> |
| </security> |
| </system.webServer> |
| </configuration>' |
| ); |
| } |
| } |
|
|
| public static function deleteWebConfigFiles() |
| { |
| $path = PIWIK_INCLUDE_PATH; |
| @unlink($path . '/web.config'); |
| @unlink($path . '/libs/web.config'); |
| @unlink($path . '/vendor/web.config'); |
| @unlink($path . '/plugins/web.config'); |
| @unlink($path . '/node_modules/web.config'); |
| @unlink($path . '/misc/web.config'); |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| public static function createWebRootFiles() |
| { |
| $filesToCreate = array( |
| '/robots.txt', |
| '/favicon.ico', |
| ); |
| foreach ($filesToCreate as $file) { |
| $path = PIWIK_DOCUMENT_ROOT . $file; |
| if (!file_exists($path)) { |
| @file_put_contents($path, ''); |
| } |
| } |
| } |
|
|
| |
| |
| |
| protected static function getDenyAllHtaccessContent() |
| { |
| $deny = self::getDenyHtaccessContent(); |
| $denyAll = |
| "# First, deny access to all files in this directory\n" . |
| "<Files \"*\">\n" . |
| $deny . "\n" . |
| "</Files>\n"; |
|
|
| return $denyAll; |
| } |
|
|
| |
| |
| |
| public static function getDenyHtaccessContent() |
| { |
| |
| |
| |
| |
| |
| |
| |
| |
| $deny = <<<HTACCESS_DENY |
| <IfModule mod_version.c> |
| <IfVersion < 2.4> |
| Order Deny,Allow |
| Deny from All |
| </IfVersion> |
| <IfVersion >= 2.4> |
| Require all denied |
| </IfVersion> |
| </IfModule> |
| <IfModule !mod_version.c> |
| <IfModule !mod_authz_core.c> |
| Order Deny,Allow |
| Deny from All |
| </IfModule> |
| <IfModule mod_authz_core.c> |
| Require all denied |
| </IfModule> |
| </IfModule> |
| HTACCESS_DENY; |
| return $deny; |
| } |
|
|
| |
| |
| |
| public static function getAllowHtaccessContent() |
| { |
| $allow = <<<HTACCESS_ALLOW |
| <IfModule mod_version.c> |
| <IfVersion < 2.4> |
| Order Allow,Deny |
| Allow from All |
| </IfVersion> |
| <IfVersion >= 2.4> |
| Require all granted |
| </IfVersion> |
| </IfModule> |
| <IfModule !mod_version.c> |
| <IfModule !mod_authz_core.c> |
| Order Allow,Deny |
| Allow from All |
| </IfModule> |
| <IfModule mod_authz_core.c> |
| Require all granted |
| </IfModule> |
| </IfModule> |
| HTACCESS_ALLOW; |
| return $allow; |
| } |
|
|
| |
| |
| |
| public static function deleteHtAccessFiles() |
| { |
| $files = Filesystem::globr(PIWIK_INCLUDE_PATH, ".htaccess"); |
|
|
| |
| |
| $directoriesWithAutoHtaccess = array( |
| '/js', |
| '/libs', |
| '/vendor', |
| '/plugins', |
| '/misc', |
| '/node_modules', |
| '/config', |
| '/core', |
| '/lang', |
| '/tmp', |
| ); |
|
|
| foreach ($files as $file) { |
| foreach ($directoriesWithAutoHtaccess as $dirToDelete) { |
| |
| $pathToDelete = $dirToDelete . '/.htaccess'; |
| if (strpos($file, $pathToDelete) !== false) { |
| @unlink($file); |
| } |
| } |
| } |
| } |
| } |
|
|