diff options
Diffstat (limited to 'lib/base.php')
-rw-r--r-- | lib/base.php | 175 |
1 files changed, 117 insertions, 58 deletions
diff --git a/lib/base.php b/lib/base.php index 525d290931f..1f7d0c0da65 100644 --- a/lib/base.php +++ b/lib/base.php @@ -74,11 +74,6 @@ class OC { public static $CLI = false; /** - * @var OC_Router - */ - protected static $router = null; - - /** * @var \OC\Session\Session */ public static $session = null; @@ -103,7 +98,9 @@ class OC { get_include_path() ); - if(defined('PHPUNIT_RUN') and PHPUNIT_RUN and is_dir(OC::$SERVERROOT . '/tests/config/')) { + if(defined('PHPUNIT_CONFIG_DIR')) { + self::$configDir = OC::$SERVERROOT . '/' . PHPUNIT_CONFIG_DIR . '/'; + } elseif(defined('PHPUNIT_RUN') and PHPUNIT_RUN and is_dir(OC::$SERVERROOT . '/tests/config/')) { self::$configDir = OC::$SERVERROOT . '/tests/config/'; } else { self::$configDir = OC::$SERVERROOT . '/config/'; @@ -188,7 +185,6 @@ class OC { if (file_exists(self::$configDir . "/config.php") and !is_writable(self::$configDir . "/config.php") ) { - $defaults = new OC_Defaults(); if (self::$CLI) { echo "Can't write into config directory!\n"; echo "This can usually be fixed by giving the webserver write access to the config directory\n"; @@ -216,6 +212,34 @@ class OC { } } + /* + * This function adds some security related headers to all requests served via base.php + * The implementation of this function has to happen here to ensure that all third-party + * components (e.g. SabreDAV) also benefit from this headers. + */ + public static function addSecurityHeaders() { + header('X-XSS-Protection: 1; mode=block'); // Enforce browser based XSS filters + header('X-Content-Type-Options: nosniff'); // Disable sniffing the content type for IE + + // iFrame Restriction Policy + $xFramePolicy = OC_Config::getValue('xframe_restriction', true); + if($xFramePolicy) { + header('X-Frame-Options: Sameorigin'); // Disallow iFraming from other domains + } + + // Content Security Policy + // If you change the standard policy, please also change it in config.sample.php + $policy = OC_Config::getValue('custom_csp_policy', + 'default-src \'self\'; ' + .'script-src \'self\' \'unsafe-eval\'; ' + .'style-src \'self\' \'unsafe-inline\'; ' + .'frame-src *; ' + .'img-src *; ' + .'font-src \'self\' data:; ' + .'media-src *'); + header('Content-Security-Policy:'.$policy); + } + public static function checkSSL() { // redirect to https site if configured if (OC_Config::getValue("forcessl", false)) { @@ -280,6 +304,11 @@ class OC { } } + /** + * Checks if the version requires an update and shows + * @param bool $showTemplate Whether an update screen should get shown + * @return bool|void + */ public static function checkUpgrade($showTemplate = true) { if (self::needUpgrade()) { if ($showTemplate && !OC_Config::getValue('maintenance', false)) { @@ -308,6 +337,7 @@ class OC { OC_Util::addScript("jquery.placeholder"); OC_Util::addScript("jquery-tipsy"); OC_Util::addScript("compatibility"); + OC_Util::addScript("underscore"); OC_Util::addScript("jquery.ocdialog"); OC_Util::addScript("oc-dialogs"); OC_Util::addScript("js"); @@ -316,7 +346,6 @@ class OC { OC_Util::addScript("config"); //OC_Util::addScript( "multiselect" ); OC_Util::addScript('search', 'result'); - OC_Util::addScript('router'); OC_Util::addScript("oc-requesttoken"); // avatars @@ -388,19 +417,6 @@ class OC { return OC_Config::getValue('session_lifetime', 60 * 60 * 24); } - /** - * @return OC_Router - */ - public static function getRouter() { - if (!isset(OC::$router)) { - OC::$router = new OC_Router(); - OC::$router->loadRoutes(); - } - - return OC::$router; - } - - public static function loadAppClassPaths() { foreach (OC_APP::getEnabledApps() as $app) { $file = OC_App::getAppPath($app) . '/appinfo/classpath.php'; @@ -420,6 +436,7 @@ class OC { self::$loader->registerPrefix('Symfony\\Component\\Routing', 'symfony/routing'); self::$loader->registerPrefix('Symfony\\Component\\Console', 'symfony/console'); self::$loader->registerPrefix('Patchwork', '3rdparty'); + self::$loader->registerPrefix('Pimple', '3rdparty/Pimple'); spl_autoload_register(array(self::$loader, 'load')); // set some stuff @@ -528,6 +545,7 @@ class OC { self::checkConfig(); self::checkInstalled(); self::checkSSL(); + self::addSecurityHeaders(); $errors = OC_Util::checkServer(); if (count($errors) > 0) { @@ -537,6 +555,7 @@ class OC { echo $error['hint'] . "\n\n"; } } else { + OC_Response::setStatus(OC_Response::STATUS_SERVICE_UNAVAILABLE); OC_Template::printGuestPage('', 'error', array('errors' => $errors)); } exit; @@ -554,26 +573,10 @@ class OC { OC_User::useBackend(new OC_User_Database()); OC_Group::useBackend(new OC_Group_Database()); - if (isset($_SERVER['PHP_AUTH_USER']) && self::$session->exists('loginname') - && $_SERVER['PHP_AUTH_USER'] !== self::$session->get('loginname')) { - $sessionUser = self::$session->get('loginname'); - $serverUser = $_SERVER['PHP_AUTH_USER']; - OC_Log::write('core', - "Session loginname ($sessionUser) doesn't match SERVER[PHP_AUTH_USER] ($serverUser).", - OC_Log::WARN); - OC_User::logout(); - } - - // Load Apps - // This includes plugins for users and filesystems as well - global $RUNTIME_NOAPPS; - global $RUNTIME_APPTYPES; - if (!$RUNTIME_NOAPPS && !self::checkUpgrade(false)) { - if ($RUNTIME_APPTYPES) { - OC_App::loadApps($RUNTIME_APPTYPES); - } else { - OC_App::loadApps(); - } + // Load minimum set of apps - which is filesystem, authentication and logging + if (!self::checkUpgrade(false)) { + OC_App::loadApps(array('authentication')); + OC_App::loadApps(array('filesystem', 'logging')); } //setup extra user backends @@ -661,7 +664,10 @@ class OC { */ public static function registerPreviewHooks() { OC_Hook::connect('OC_Filesystem', 'post_write', 'OC\Preview', 'post_write'); - OC_Hook::connect('OC_Filesystem', 'delete', 'OC\Preview', 'post_delete'); + OC_Hook::connect('OC_Filesystem', 'preDelete', 'OC\Preview', 'prepare_delete_files'); + OC_Hook::connect('\OCP\Versions', 'preDelete', 'OC\Preview', 'prepare_delete'); + OC_Hook::connect('\OCP\Trashbin', 'preDelete', 'OC\Preview', 'prepare_delete'); + OC_Hook::connect('OC_Filesystem', 'delete', 'OC\Preview', 'post_delete_files'); OC_Hook::connect('\OCP\Versions', 'delete', 'OC\Preview', 'post_delete'); OC_Hook::connect('\OCP\Trashbin', 'delete', 'OC\Preview', 'post_delete'); } @@ -671,10 +677,10 @@ class OC { */ public static function registerShareHooks() { if (\OC_Config::getValue('installed')) { - OC_Hook::connect('OC_User', 'post_deleteUser', 'OCP\Share', 'post_deleteUser'); - OC_Hook::connect('OC_User', 'post_addToGroup', 'OCP\Share', 'post_addToGroup'); - OC_Hook::connect('OC_User', 'post_removeFromGroup', 'OCP\Share', 'post_removeFromGroup'); - OC_Hook::connect('OC_User', 'post_deleteGroup', 'OCP\Share', 'post_deleteGroup'); + OC_Hook::connect('OC_User', 'post_deleteUser', 'OC\Share\Hooks', 'post_deleteUser'); + OC_Hook::connect('OC_User', 'post_addToGroup', 'OC\Share\Hooks', 'post_addToGroup'); + OC_Hook::connect('OC_User', 'post_removeFromGroup', 'OC\Share\Hooks', 'post_removeFromGroup'); + OC_Hook::connect('OC_User', 'post_deleteGroup', 'OC\Share\Hooks', 'post_deleteGroup'); } } @@ -682,6 +688,7 @@ class OC { * @brief Handle the request */ public static function handleRequest() { + $l = \OC_L10N::get('lib'); // load all the classpaths from the enabled apps so they are available // in the routing files of each app OC::loadAppClassPaths(); @@ -693,14 +700,32 @@ class OC { exit(); } + $host = OC_Request::insecureServerHost(); + // if the host passed in headers isn't trusted + if (!OC::$CLI + // overwritehost is always trusted + && OC_Request::getOverwriteHost() === null + && !OC_Request::isTrustedDomain($host)) { + + header('HTTP/1.1 400 Bad Request'); + header('Status: 400 Bad Request'); + OC_Template::printErrorPage( + $l->t('You are accessing the server from an untrusted domain.'), + $l->t('Please contact your administrator. If you are an administrator of this instance, configure the "trusted_domain" setting in config/config.php. An example configuration is provided in config/config.sample.php.') + ); + return; + } + $request = OC_Request::getPathInfo(); if (substr($request, -3) !== '.js') { // we need these files during the upgrade self::checkMaintenanceMode(); self::checkUpgrade(); } - // Test it the user is already authenticated using Apaches AuthType Basic... very usable in combination with LDAP - OC::tryBasicAuthLogin(); + if (!OC_User::isLoggedIn()) { + // Test it the user is already authenticated using Apaches AuthType Basic... very usable in combination with LDAP + OC::tryBasicAuthLogin(); + } if (!self::$CLI and (!isset($_GET["logout"]) or ($_GET["logout"] !== 'true'))) { try { @@ -708,7 +733,7 @@ class OC { OC_App::loadApps(); } self::checkSingleUserMode(); - OC::getRouter()->match(OC_Request::getRawPathInfo()); + OC::$server->getRouter()->match(OC_Request::getRawPathInfo()); return; } catch (Symfony\Component\Routing\Exception\ResourceNotFoundException $e) { //header('HTTP/1.0 404 Not Found'); @@ -751,8 +776,18 @@ class OC { if (isset($_COOKIE['oc_token'])) { OC_Preferences::deleteKey(OC_User::getUser(), 'login_token', $_COOKIE['oc_token']); } + if (isset($_SERVER['PHP_AUTH_USER'])) { + if (isset($_COOKIE['oc_ignore_php_auth_user'])) { + // Ignore HTTP Authentication for 5 more mintues. + setcookie('oc_ignore_php_auth_user', $_SERVER['PHP_AUTH_USER'], time() + 300, OC::$WEBROOT.(empty(OC::$WEBROOT) ? '/' : '')); + } elseif ($_SERVER['PHP_AUTH_USER'] === self::$session->get('loginname')) { + // Ignore HTTP Authentication to allow a different user to log in. + setcookie('oc_ignore_php_auth_user', $_SERVER['PHP_AUTH_USER'], 0, OC::$WEBROOT.(empty(OC::$WEBROOT) ? '/' : '')); + } + } OC_User::logout(); - header("Location: " . OC::$WEBROOT . '/'); + // redirect to webroot and add slash if webroot is empty + header("Location: " . OC::$WEBROOT.(empty(OC::$WEBROOT) ? '/' : '')); } else { if (is_null($file)) { $param['file'] = 'index.php'; @@ -770,6 +805,11 @@ class OC { self::handleLogin(); } + /** + * Load a PHP file belonging to the specified application + * @param array $param The application and file to load + * @return bool Whether the file has been found (will return 404 and false if not) + */ public static function loadAppScriptFile($param) { OC_App::loadApps(); $app = $param['app']; @@ -812,6 +852,10 @@ class OC { OC_Util::displayLoginPage(array_unique($error)); } + /** + * Remove outdated and therefore invalid tokens for a user + * @param string $user + */ protected static function cleanupLoginTokens($user) { $cutoff = time() - OC_Config::getValue('remember_login_cookie_lifetime', 60 * 60 * 24 * 15); $tokens = OC_Preferences::getKeys($user, 'login_token'); @@ -823,6 +867,10 @@ class OC { } } + /** + * Try to login a user via HTTP authentication + * @return bool|void + */ protected static function tryApacheAuth() { $return = OC_User::handleApacheAuth(); @@ -837,6 +885,10 @@ class OC { return is_null($return) ? false : true; } + /** + * Try to login a user using the remember me cookie. + * @return bool Whether the provided cookie was valid + */ protected static function tryRememberLogin() { if (!isset($_COOKIE["oc_remember_login"]) || !isset($_COOKIE["oc_token"]) @@ -846,7 +898,7 @@ class OC { ) { return false; } - OC_App::loadApps(array('authentication')); + if (defined("DEBUG") && DEBUG) { OC_Log::write('core', 'Trying to login from cookie', OC_Log::DEBUG); } @@ -878,6 +930,10 @@ class OC { return true; } + /** + * Tries to login a user using the formbased authentication + * @return bool|void + */ protected static function tryFormLogin() { if (!isset($_POST["user"]) || !isset($_POST['password'])) { return false; @@ -912,13 +968,18 @@ class OC { return true; } + /** + * Try to login a user using HTTP authentication. + * @return bool + */ protected static function tryBasicAuthLogin() { if (!isset($_SERVER["PHP_AUTH_USER"]) || !isset($_SERVER["PHP_AUTH_PW"]) + || (isset($_COOKIE['oc_ignore_php_auth_user']) && $_COOKIE['oc_ignore_php_auth_user'] === $_SERVER['PHP_AUTH_USER']) ) { return false; } - OC_App::loadApps(array('authentication')); + if (OC_User::login($_SERVER["PHP_AUTH_USER"], $_SERVER["PHP_AUTH_PW"])) { //OC_Log::write('core',"Logged in with HTTP Authentication", OC_Log::DEBUG); OC_User::unsetMagicInCookie(); @@ -929,12 +990,11 @@ class OC { } -// define runtime variables - unless this already has been done -if (!isset($RUNTIME_NOAPPS)) { - $RUNTIME_NOAPPS = false; -} - if (!function_exists('get_temp_dir')) { + /** + * Get the temporary dir to store uploaded data + * @return null|string Path to the temporary directory or null + */ function get_temp_dir() { if ($temp = ini_get('upload_tmp_dir')) return $temp; if ($temp = getenv('TMP')) return $temp; @@ -952,4 +1012,3 @@ if (!function_exists('get_temp_dir')) { } OC::init(); - |