public function preRequest(HTTPRequest $request, Session $session, DataModel $model)
 {
     // Bootstrap session so that Session::get() accesses the right instance
     $dummyController = new Controller();
     $dummyController->setSession($session);
     $dummyController->setRequest($request);
     $dummyController->pushCurrent();
     // Block non-authenticated users from setting the stage mode
     if (!Versioned::can_choose_site_stage($request)) {
         $permissionMessage = sprintf(_t("ContentController.DRAFT_SITE_ACCESS_RESTRICTION", 'You must log in with your CMS password in order to view the draft or archived content. ' . '<a href="%s">Click here to go back to the published site.</a>'), Convert::raw2xml(Controller::join_links(Director::baseURL(), $request->getURL(), "?stage=Live")));
         // Force output since RequestFilter::preRequest doesn't support response overriding
         $response = Security::permissionFailure($dummyController, $permissionMessage);
         $session->inst_save();
         $dummyController->popCurrent();
         // Prevent output in testing
         if (class_exists('SilverStripe\\Dev\\SapphireTest', false) && SapphireTest::is_running_test()) {
             throw new HTTPResponse_Exception($response);
         }
         $response->output();
         die;
     }
     Versioned::choose_site_stage();
     $dummyController->popCurrent();
     return true;
 }
 protected function init()
 {
     parent::init();
     $isRunningTests = class_exists('SilverStripe\\Dev\\SapphireTest', false) && SapphireTest::is_running_test();
     $canAccess = Director::isDev() || Director::is_cli() && !$isRunningTests || Permission::check("ADMIN");
     if (!$canAccess) {
         Security::permissionFailure($this);
     }
 }
 /**
  * Require basic authentication.  Will request a username and password if none is given.
  *
  * Used by {@link Controller::init()}.
  *
  * @throws HTTPResponse_Exception
  *
  * @param string $realm
  * @param string|array $permissionCode Optional
  * @param boolean $tryUsingSessionLogin If true, then the method with authenticate against the
  *  session log-in if those credentials are disabled.
  * @return Member|bool $member
  */
 public static function requireLogin($realm, $permissionCode = null, $tryUsingSessionLogin = true)
 {
     $isRunningTests = class_exists('SilverStripe\\Dev\\SapphireTest', false) && SapphireTest::is_running_test();
     if (!Security::database_is_ready() || Director::is_cli() && !$isRunningTests) {
         return true;
     }
     /*
      * Enable HTTP Basic authentication workaround for PHP running in CGI mode with Apache
      * Depending on server configuration the auth header may be in HTTP_AUTHORIZATION or
      * REDIRECT_HTTP_AUTHORIZATION
      *
      * The follow rewrite rule must be in the sites .htaccess file to enable this workaround
      * RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
      */
     $authHeader = isset($_SERVER['HTTP_AUTHORIZATION']) ? $_SERVER['HTTP_AUTHORIZATION'] : (isset($_SERVER['REDIRECT_HTTP_AUTHORIZATION']) ? $_SERVER['REDIRECT_HTTP_AUTHORIZATION'] : null);
     $matches = array();
     if ($authHeader && preg_match('/Basic\\s+(.*)$/i', $authHeader, $matches)) {
         list($name, $password) = explode(':', base64_decode($matches[1]));
         $_SERVER['PHP_AUTH_USER'] = strip_tags($name);
         $_SERVER['PHP_AUTH_PW'] = strip_tags($password);
     }
     $member = null;
     if (isset($_SERVER['PHP_AUTH_USER']) && isset($_SERVER['PHP_AUTH_PW'])) {
         $member = MemberAuthenticator::authenticate(array('Email' => $_SERVER['PHP_AUTH_USER'], 'Password' => $_SERVER['PHP_AUTH_PW']), null);
     }
     if (!$member && $tryUsingSessionLogin) {
         $member = Member::currentUser();
     }
     // If we've failed the authentication mechanism, then show the login form
     if (!$member) {
         $response = new HTTPResponse(null, 401);
         $response->addHeader('WWW-Authenticate', "Basic realm=\"{$realm}\"");
         if (isset($_SERVER['PHP_AUTH_USER'])) {
             $response->setBody(_t('BasicAuth.ERRORNOTREC', "That username / password isn't recognised"));
         } else {
             $response->setBody(_t('BasicAuth.ENTERINFO', "Please enter a username and password."));
         }
         // Exception is caught by RequestHandler->handleRequest() and will halt further execution
         $e = new HTTPResponse_Exception(null, 401);
         $e->setResponse($response);
         throw $e;
     }
     if ($permissionCode && !Permission::checkMember($member->ID, $permissionCode)) {
         $response = new HTTPResponse(null, 401);
         $response->addHeader('WWW-Authenticate', "Basic realm=\"{$realm}\"");
         if (isset($_SERVER['PHP_AUTH_USER'])) {
             $response->setBody(_t('BasicAuth.ERRORNOTADMIN', "That user is not an administrator."));
         }
         // Exception is caught by RequestHandler->handleRequest() and will halt further execution
         $e = new HTTPResponse_Exception(null, 401);
         $e->setResponse($response);
         throw $e;
     }
     return $member;
 }
 protected function init()
 {
     parent::init();
     // We allow access to this controller regardless of live-status or ADMIN permission only
     // if on CLI or with the database not ready. The latter makes it less errorprone to do an
     // initial schema build without requiring a default-admin login.
     // Access to this controller is always allowed in "dev-mode", or of the user is ADMIN.
     $isRunningTests = class_exists('SilverStripe\\Dev\\SapphireTest', false) && SapphireTest::is_running_test();
     $canAccess = Director::isDev() || !Security::database_is_ready() || Director::is_cli() && !$isRunningTests || Permission::check("ADMIN");
     if (!$canAccess) {
         Security::permissionFailure($this, "This page is secured and you need administrator rights to access it. " . "Enter your credentials below and we will send you right along.");
     }
 }
 /**
  * Force the site to run on SSL.
  *
  * To use, call from _config.php. For example:
  * <code>
  * if (Director::isLive()) Director::forceSSL();
  * </code>
  *
  * If you don't want your entire site to be on SSL, you can pass an array of PCRE regular expression
  * patterns for matching relative URLs. For example:
  * <code>
  * if (Director::isLive()) Director::forceSSL(array('/^admin/', '/^Security/'));
  * </code>
  *
  * If you want certain parts of your site protected under a different domain, you can specify
  * the domain as an argument:
  * <code>
  * if (Director::isLive()) Director::forceSSL(array('/^admin/', '/^Security/'), 'secure.mysite.com');
  * </code>
  *
  * Note that the session data will be lost when moving from HTTP to HTTPS. It is your responsibility
  * to ensure that this won't cause usability problems.
  *
  * CAUTION: This does not respect the site environment mode. You should check this
  * as per the above examples using Director::isLive() or Director::isTest() for example.
  *
  * @param array $patterns Array of regex patterns to match URLs that should be HTTPS.
  * @param string $secureDomain Secure domain to redirect to. Defaults to the current domain.
  *
  * @return bool|string String of URL when unit tests running, boolean FALSE if patterns don't match request URI.
  */
 public static function forceSSL($patterns = null, $secureDomain = null)
 {
     // Calling from the command-line?
     if (!isset($_SERVER['REQUEST_URI'])) {
         return false;
     }
     $matched = false;
     if ($patterns) {
         $relativeURL = self::makeRelative(Director::absoluteURL($_SERVER['REQUEST_URI']));
         // protect portions of the site based on the pattern
         foreach ($patterns as $pattern) {
             if (preg_match($pattern, $relativeURL)) {
                 $matched = true;
                 break;
             }
         }
     } else {
         // protect the entire site
         $matched = true;
     }
     if ($matched && !self::is_https()) {
         // if an domain is specified, redirect to that instead of the current domain
         if ($secureDomain) {
             $url = 'https://' . $secureDomain . $_SERVER['REQUEST_URI'];
         } else {
             $url = $_SERVER['REQUEST_URI'];
         }
         $destURL = str_replace('http:', 'https:', Director::absoluteURL($url));
         // This coupling to SapphireTest is necessary to test the destination URL and to not interfere with tests
         if (class_exists('SilverStripe\\Dev\\SapphireTest', false) && SapphireTest::is_running_test()) {
             return $destURL;
         } else {
             self::force_redirect($destURL);
             return true;
         }
     } else {
         return false;
     }
 }
 /**
  * Check that a valid file was given for upload (ignores file size)
  *
  * @return bool
  */
 public function isValidUpload()
 {
     // Check file upload
     if ($this->tmpFile['error'] === UPLOAD_ERR_NO_FILE) {
         return false;
     }
     // Check if file is valid uploaded (with exception for unit testing)
     // Note that some "max file size" errors leave "temp_name" empty, so don't fail on this.
     $isRunningTests = class_exists('SilverStripe\\Dev\\SapphireTest', false) && SapphireTest::is_running_test();
     if (!empty($this->tmpFile['tmp_name']) && !is_uploaded_file($this->tmpFile['tmp_name']) && !$isRunningTests) {
         return false;
     }
     return true;
 }
Ejemplo n.º 7
0
 /**
  * Log the user in if the "remember login" cookie is set
  *
  * The <i>remember login token</i> will be changed on every successful
  * auto-login.
  */
 public static function autoLogin()
 {
     // Don't bother trying this multiple times
     if (!class_exists('SilverStripe\\Dev\\SapphireTest', false) || !SapphireTest::is_running_test()) {
         self::$_already_tried_to_auto_log_in = true;
     }
     if (!Security::config()->autologin_enabled || strpos(Cookie::get('alc_enc'), ':') === false || Session::get("loggedInAs") || !Security::database_is_ready()) {
         return;
     }
     if (strpos(Cookie::get('alc_enc'), ':') && Cookie::get('alc_device') && !Session::get("loggedInAs")) {
         list($uid, $token) = explode(':', Cookie::get('alc_enc'), 2);
         if (!$uid || !$token) {
             return;
         }
         $deviceID = Cookie::get('alc_device');
         /** @var Member $member */
         $member = Member::get()->byID($uid);
         /** @var RememberLoginHash $rememberLoginHash */
         $rememberLoginHash = null;
         // check if autologin token matches
         if ($member) {
             $hash = $member->encryptWithUserSettings($token);
             $rememberLoginHash = RememberLoginHash::get()->filter(array('MemberID' => $member->ID, 'DeviceID' => $deviceID, 'Hash' => $hash))->first();
             if (!$rememberLoginHash) {
                 $member = null;
             } else {
                 // Check for expired token
                 $expiryDate = new DateTime($rememberLoginHash->ExpiryDate);
                 $now = DBDatetime::now();
                 $now = new DateTime($now->Rfc2822());
                 if ($now > $expiryDate) {
                     $member = null;
                 }
             }
         }
         if ($member) {
             self::session_regenerate_id();
             Session::set("loggedInAs", $member->ID);
             // This lets apache rules detect whether the user has logged in
             if (Member::config()->login_marker_cookie) {
                 Cookie::set(Member::config()->login_marker_cookie, 1, 0, null, null, false, true);
             }
             if ($rememberLoginHash) {
                 $rememberLoginHash->renew();
                 $tokenExpiryDays = RememberLoginHash::config()->get('token_expiry_days');
                 Cookie::set('alc_enc', $member->ID . ':' . $rememberLoginHash->getToken(), $tokenExpiryDays, null, null, false, true);
             }
             $member->write();
             // Audit logging hook
             $member->extend('memberAutoLoggedIn');
         }
     }
 }