]>
Commit | Line | Data |
---|---|---|
ebd650c0 V |
1 | <?php |
2 | namespace Shaarli; | |
3 | ||
c7721487 V |
4 | use Shaarli\Config\ConfigManager; |
5 | ||
ebd650c0 V |
6 | /** |
7 | * Manages the server-side session | |
8 | */ | |
9 | class SessionManager | |
10 | { | |
c7721487 | 11 | /** @var int Session expiration timeout, in seconds */ |
db45a36a V |
12 | public static $INACTIVITY_TIMEOUT = 3600; |
13 | ||
c7721487 | 14 | /** @var string Name of the cookie set after logging in **/ |
49f18323 V |
15 | public static $LOGGED_IN_COOKIE = 'shaarli_staySignedIn'; |
16 | ||
c7721487 | 17 | /** @var array Local reference to the global $_SESSION array */ |
ebd650c0 V |
18 | protected $session = []; |
19 | ||
c7721487 | 20 | /** @var ConfigManager Configuration Manager instance **/ |
49f18323 V |
21 | protected $conf = null; |
22 | ||
ebd650c0 V |
23 | /** |
24 | * Constructor | |
25 | * | |
26 | * @param array $session The $_SESSION array (reference) | |
dd883aaf | 27 | * @param ConfigManager $conf ConfigManager instance |
ebd650c0 | 28 | */ |
dd883aaf | 29 | public function __construct(& $session, $conf) |
ebd650c0 V |
30 | { |
31 | $this->session = &$session; | |
dd883aaf | 32 | $this->conf = $conf; |
ebd650c0 V |
33 | } |
34 | ||
35 | /** | |
36 | * Generates a session token | |
37 | * | |
38 | * @return string token | |
39 | */ | |
40 | public function generateToken() | |
41 | { | |
42 | $token = sha1(uniqid('', true) .'_'. mt_rand() . $this->conf->get('credentials.salt')); | |
43 | $this->session['tokens'][$token] = 1; | |
44 | return $token; | |
45 | } | |
46 | ||
47 | /** | |
48 | * Checks the validity of a session token, and destroys it afterwards | |
49 | * | |
50 | * @param string $token The token to check | |
51 | * | |
52 | * @return bool true if the token is valid, else false | |
53 | */ | |
54 | public function checkToken($token) | |
55 | { | |
56 | if (! isset($this->session['tokens'][$token])) { | |
57 | // the token is wrong, or has already been used | |
58 | return false; | |
59 | } | |
60 | ||
61 | // destroy the token to prevent future use | |
62 | unset($this->session['tokens'][$token]); | |
63 | return true; | |
64 | } | |
fd7d8461 V |
65 | |
66 | /** | |
67 | * Validate session ID to prevent Full Path Disclosure. | |
68 | * | |
69 | * See #298. | |
70 | * The session ID's format depends on the hash algorithm set in PHP settings | |
71 | * | |
72 | * @param string $sessionId Session ID | |
73 | * | |
74 | * @return true if valid, false otherwise. | |
75 | * | |
76 | * @see http://php.net/manual/en/function.hash-algos.php | |
77 | * @see http://php.net/manual/en/session.configuration.php | |
78 | */ | |
79 | public static function checkId($sessionId) | |
80 | { | |
81 | if (empty($sessionId)) { | |
82 | return false; | |
83 | } | |
84 | ||
85 | if (!$sessionId) { | |
86 | return false; | |
87 | } | |
88 | ||
89 | if (!preg_match('/^[a-zA-Z0-9,-]{2,128}$/', $sessionId)) { | |
90 | return false; | |
91 | } | |
92 | ||
93 | return true; | |
94 | } | |
49f18323 V |
95 | |
96 | /** | |
97 | * Store user login information after a successful login | |
98 | * | |
c7721487 | 99 | * @param string $clientIpId Client IP address identifier |
49f18323 | 100 | */ |
c7721487 | 101 | public function storeLoginInfo($clientIpId) |
49f18323 V |
102 | { |
103 | // Generate unique random number (different than phpsessionid) | |
104 | $this->session['uid'] = sha1(uniqid('', true) . '_' . mt_rand()); | |
c7721487 | 105 | $this->session['ip'] = $clientIpId; |
49f18323 V |
106 | $this->session['username'] = $this->conf->get('credentials.login'); |
107 | $this->session['expires_on'] = time() + self::$INACTIVITY_TIMEOUT; | |
108 | } | |
109 | ||
c7721487 V |
110 | /** |
111 | * Extend session validity | |
112 | */ | |
113 | public function extendSession() | |
114 | { | |
115 | if (! empty($this->session['longlastingsession'])) { | |
116 | // "Stay signed in" is enabled | |
117 | $this->session['expires_on'] = time() + $this->session['longlastingsession']; | |
118 | return; | |
119 | } | |
120 | $this->session['expires_on'] = time() + self::$INACTIVITY_TIMEOUT; | |
121 | } | |
122 | ||
49f18323 V |
123 | /** |
124 | * Logout a user by unsetting all login information | |
125 | * | |
126 | * See: | |
127 | * - https://secure.php.net/manual/en/function.setcookie.php | |
128 | * | |
129 | * @param string $webPath path on the server in which the cookie will be available on | |
130 | */ | |
131 | public function logout($webPath) | |
132 | { | |
133 | if (isset($this->session)) { | |
134 | unset($this->session['uid']); | |
135 | unset($this->session['ip']); | |
136 | unset($this->session['username']); | |
137 | unset($this->session['visibility']); | |
138 | unset($this->session['untaggedonly']); | |
139 | } | |
140 | setcookie(self::$LOGGED_IN_COOKIE, 'false', 0, $webPath); | |
141 | } | |
c7721487 V |
142 | |
143 | /** | |
144 | * Check whether the session has expired | |
145 | * | |
146 | * @param string $clientIpId Client IP address identifier | |
147 | * | |
148 | * @return bool true if the session has expired, false otherwise | |
149 | */ | |
150 | public function hasSessionExpired() | |
151 | { | |
152 | if (empty($this->session['uid'])) { | |
153 | return true; | |
154 | } | |
155 | if (time() >= $this->session['expires_on']) { | |
156 | return true; | |
157 | } | |
158 | return false; | |
159 | } | |
160 | ||
161 | /** | |
162 | * Check whether the client IP address has changed | |
163 | * | |
164 | * @param string $clientIpId Client IP address identifier | |
165 | * | |
166 | * @return bool true if the IP has changed, false if it has not, or | |
167 | * if session protection has been disabled | |
168 | */ | |
169 | public function hasClientIpChanged($clientIpId) | |
170 | { | |
171 | if ($this->conf->get('security.session_protection_disabled') === true) { | |
172 | return false; | |
173 | } | |
174 | if ($this->session['ip'] == $clientIpId) { | |
175 | return false; | |
176 | } | |
177 | return true; | |
178 | } | |
ebd650c0 | 179 | } |