Upgraded drupal core with security updates
[yaffs-website] / web / core / lib / Drupal / Core / Session / SessionConfiguration.php
1 <?php
2
3 namespace Drupal\Core\Session;
4
5 use Symfony\Component\HttpFoundation\Request;
6
7 /**
8  * Defines the default session configuration generator.
9  */
10 class SessionConfiguration implements SessionConfigurationInterface {
11
12   /**
13    * An associative array of session ini settings.
14    */
15   protected $options;
16
17   /**
18    * Constructs a new session configuration instance.
19    *
20    * @param array $options
21    *   An associative array of session ini settings.
22    *
23    * @see \Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage::__construct()
24    * @see http://php.net/manual/session.configuration.php
25    */
26   public function __construct($options = []) {
27     $this->options = $options;
28   }
29
30   /**
31    * {@inheritdoc}
32    */
33   public function hasSession(Request $request) {
34     return $request->cookies->has($this->getName($request));
35   }
36
37   /**
38    * {@inheritdoc}
39    */
40   public function getOptions(Request $request) {
41     $options = $this->options;
42
43     // Generate / validate the cookie domain.
44     $options['cookie_domain'] = $this->getCookieDomain($request) ?: '';
45
46     // If the site is accessed via SSL, ensure that the session cookie is
47     // issued with the secure flag.
48     $options['cookie_secure'] = $request->isSecure();
49
50     // Set the session cookie name.
51     $options['name'] = $this->getName($request);
52
53     return $options;
54   }
55
56   /**
57    * Returns the session cookie name.
58    *
59    * @param \Symfony\Component\HttpFoundation\Request $request
60    *   The request.
61    *
62    * @return string
63    *   The name of the session cookie.
64    */
65   protected function getName(Request $request) {
66     // To prevent session cookies from being hijacked, a user can configure the
67     // SSL version of their website to only transfer session cookies via SSL by
68     // using PHP's session.cookie_secure setting. The browser will then use two
69     // separate session cookies for the HTTPS and HTTP versions of the site. So
70     // we must use different session identifiers for HTTPS and HTTP to prevent a
71     // cookie collision.
72     $prefix = $request->isSecure() ? 'SSESS' : 'SESS';
73     return $prefix . $this->getUnprefixedName($request);
74   }
75
76   /**
77    * Returns the session cookie name without the secure/insecure prefix.
78    *
79    * @param \Symfony\Component\HttpFoundation\Request $request
80    *   The request.
81    *
82    * @returns string
83    *   The session name without the prefix (SESS/SSESS).
84    */
85   protected function getUnprefixedName(Request $request) {
86     if ($test_prefix = $this->drupalValidTestUa()) {
87       $session_name = $test_prefix;
88     }
89     elseif (isset($this->options['cookie_domain'])) {
90       // If the user specifies the cookie domain, also use it for session name.
91       $session_name = $this->options['cookie_domain'];
92     }
93     else {
94       // Otherwise use $base_url as session name, without the protocol
95       // to use the same session identifiers across HTTP and HTTPS.
96       $session_name = $request->getHost() . $request->getBasePath();
97       // Replace "core" out of session_name so core scripts redirect properly,
98       // specifically install.php.
99       $session_name = preg_replace('#/core$#', '', $session_name);
100     }
101
102     return substr(hash('sha256', $session_name), 0, 32);
103   }
104
105   /**
106    * Return the session cookie domain.
107    *
108    * The Set-Cookie response header and its domain attribute are defined in RFC
109    * 2109, RFC 2965 and RFC 6265 each one superseeding the previous version.
110    *
111    * @see http://tools.ietf.org/html/rfc2109
112    * @see http://tools.ietf.org/html/rfc2965
113    * @see http://tools.ietf.org/html/rfc6265
114    *
115    * @param \Symfony\Component\HttpFoundation\Request $request
116    *   The request.
117    *
118    * @returns string
119    *   The session cookie domain.
120    */
121   protected function getCookieDomain(Request $request) {
122     if (isset($this->options['cookie_domain'])) {
123       $cookie_domain = $this->options['cookie_domain'];
124     }
125     else {
126       $host = $request->getHost();
127       // To maximize compatibility and normalize the behavior across user
128       // agents, the cookie domain should start with a dot.
129       $cookie_domain = '.' . $host;
130     }
131
132     // Cookies for domains without an embedded dot will be rejected by user
133     // agents in order to defeat malicious websites attempting to set cookies
134     // for top-level domains. Also IP addresses may not be used in the domain
135     // attribute of a Set-Cookie header.
136     if (count(explode('.', $cookie_domain)) > 2 && !is_numeric(str_replace('.', '', $cookie_domain))) {
137       return $cookie_domain;
138     }
139   }
140
141   /**
142    * Wraps drupal_valid_test_ua().
143    *
144    * @return string|false
145    *   Either the simpletest prefix (the string "simpletest" followed by any
146    *   number of digits) or FALSE if the user agent does not contain a valid
147    *   HMAC and timestamp.
148    */
149   protected function drupalValidTestUa() {
150     return drupal_valid_test_ua();
151   }
152
153 }