summaryrefslogtreecommitdiffstats
path: root/lib/SimpleSAML/SessionHandlerCookie.php
blob: e5c02bff6b9b671cedc800342da26f3fde2c0903 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
<?php


/**
 * This file is part of SimpleSAMLphp. See the file COPYING in the root of the distribution for licence information.
 *
 * This file defines a base class for session handlers that need to store the session id in a cookie. It takes care of
 * storing and retrieving the session id.
 *
 * @author Olav Morken, UNINETT AS. <andreas.solberg@uninett.no>
 * @package SimpleSAMLphp
 * @abstract
 */
abstract class SimpleSAML_SessionHandlerCookie extends SimpleSAML_SessionHandler
{

    /**
     * This variable contains the current session id.
     *
     * @var string|null
     */
    private $session_id = null;


    /**
     * This variable contains the session cookie name.
     *
     * @var string
     */
    protected $cookie_name;


    /**
     * This constructor initializes the session id based on what we receive in a cookie. We create a new session id and
     * set a cookie with this id if we don't have a session id.
     */
    protected function __construct()
    {
        // call the constructor in the base class in case it should become necessary in the future
        parent::__construct();

        $config = SimpleSAML_Configuration::getInstance();
        $this->cookie_name = $config->getString('session.cookie.name', 'SimpleSAMLSessionID');
    }


    /**
     * Create a new session id.
     *
     * @return string The new session id.
     */
    public function newSessionId()
    {
        $this->session_id = self::createSessionID();
        SimpleSAML_Session::createSession($this->session_id);

        return $this->session_id;
    }


    /**
     * Retrieve the session ID saved in the session cookie, if there's one.
     *
     * @return string|null The session id saved in the cookie or null if no session cookie was set.
     */
    public function getCookieSessionId()
    {
        if ($this->session_id === null) {
            if (self::hasSessionCookie()) {
                // attempt to retrieve the session id from the cookie
                $this->session_id = $_COOKIE[$this->cookie_name];
            }

            // check if we have a valid session id
            if (!self::isValidSessionID($this->session_id)) {
                // invalid, disregard this session
                return null;
            }
        }

        return $this->session_id;
    }


    /**
     * Retrieve the session cookie name.
     *
     * @return string The session cookie name.
     */
    public function getSessionCookieName()
    {
        return $this->cookie_name;
    }


    /**
     * This static function creates a session id. A session id consists of 32 random hexadecimal characters.
     *
     * @return string A random session id.
     */
    private static function createSessionID()
    {
        return bin2hex(openssl_random_pseudo_bytes(16));
    }


    /**
     * This static function validates a session id. A session id is valid if it only consists of characters which are
     * allowed in a session id and it is the correct length.
     *
     * @param string $session_id The session ID we should validate.
     *
     * @return boolean True if this session ID is valid, false otherwise.
     */
    private static function isValidSessionID($session_id)
    {
        if (!is_string($session_id)) {
            return false;
        }

        if (strlen($session_id) != 32) {
            return false;
        }

        if (preg_match('/[^0-9a-f]/', $session_id)) {
            return false;
        }

        return true;
    }


    /**
     * Check whether the session cookie is set.
     *
     * This function will only return false if is is certain that the cookie isn't set.
     *
     * @return boolean True if it was set, false otherwise.
     */
    public function hasSessionCookie()
    {
        return array_key_exists($this->cookie_name, $_COOKIE);
    }


    /**
     * Set a session cookie.
     *
     * @param string $sessionName The name of the session.
     * @param string|null $sessionID The session ID to use. Set to null to delete the cookie.
     * @param array|null $cookieParams Additional parameters to use for the session cookie.
     *
     * @throws \SimpleSAML\Error\CannotSetCookie If we can't set the cookie.
     */
    public function setCookie($sessionName, $sessionID, array $cookieParams = null)
    {
        assert('is_string($sessionName)');
        assert('is_string($sessionID) || is_null($sessionID)');

        if ($cookieParams !== null) {
            $params = array_merge($this->getCookieParams(), $cookieParams);
        } else {
            $params = $this->getCookieParams();
        }

        \SimpleSAML\Utils\HTTP::setCookie($sessionName, $sessionID, $params, true);
    }
}