Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 24 |
|
0.00% |
0 / 12 |
CRAP | |
0.00% |
0 / 1 |
SecureDelegator | |
0.00% |
0 / 24 |
|
0.00% |
0 / 12 |
272 | |
0.00% |
0 / 1 |
__construct | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
2 | |||
close | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
destroy | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
gc | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
open | |
0.00% |
0 / 9 |
|
0.00% |
0 / 1 |
12 | |||
read | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
12 | |||
write | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
enableWrites | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
disableWrites | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getDbTableManager | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
setDbTableManager | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
__call | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 |
1 | <?php |
2 | |
3 | /** |
4 | * Secure session delegator |
5 | * |
6 | * Copyright (C) Villanova University 2018, |
7 | * Leipzig University Library <info@ub.uni-leipzig.de> 2018. |
8 | * |
9 | * PHP version 8 |
10 | * |
11 | * This program is free software; you can redistribute it and/or modify |
12 | * it under the terms of the GNU General Public License version 2, |
13 | * as published by the Free Software Foundation. |
14 | * |
15 | * This program is distributed in the hope that it will be useful, |
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
18 | * GNU General Public License for more details. |
19 | * |
20 | * You should have received a copy of the GNU General Public License |
21 | * along with this program; if not, write to the Free Software |
22 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
23 | * |
24 | * @category VuFind |
25 | * @package Session_Handlers |
26 | * @author Demian Katz <demian.katz@villanova.edu> |
27 | * @author Sebastian Kehr <kehr@ub.uni-leipzig.de> |
28 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License |
29 | * @link https://vufind.org/wiki/development:plugins:session_handlers Wiki |
30 | */ |
31 | |
32 | namespace VuFind\Session; |
33 | |
34 | use Laminas\Crypt\BlockCipher; |
35 | use Laminas\Math\Rand; |
36 | use VuFind\Cookie\CookieManager; |
37 | use VuFind\Db\Table\PluginManager; |
38 | |
39 | use function func_get_args; |
40 | |
41 | /** |
42 | * Secure session delegator |
43 | * |
44 | * @category VuFind |
45 | * @package Session_Handlers |
46 | * @author Demian Katz <demian.katz@villanova.edu> |
47 | * @author Sebastian Kehr <kehr@ub.uni-leipzig.de> |
48 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License |
49 | * @link https://vufind.org/wiki/development:plugins:session_handlers Wiki |
50 | */ |
51 | class SecureDelegator implements HandlerInterface |
52 | { |
53 | /** |
54 | * The block cipher for en/decrypting session data. |
55 | * |
56 | * @var BlockCipher |
57 | */ |
58 | protected $cipher; |
59 | |
60 | /** |
61 | * VuFind cookie manager service. |
62 | * |
63 | * @var CookieManager |
64 | */ |
65 | protected $cookieManager; |
66 | |
67 | /** |
68 | * The wrapped session handler. |
69 | * |
70 | * @var HandlerInterface |
71 | */ |
72 | protected $handler; |
73 | |
74 | /** |
75 | * SecureDelegator constructor. |
76 | * |
77 | * @param CookieManager $cookieManager VuFind cookie manager service. |
78 | * @param HandlerInterface $handler The wrapped session handler. |
79 | */ |
80 | public function __construct( |
81 | CookieManager $cookieManager, |
82 | HandlerInterface $handler |
83 | ) { |
84 | $this->handler = $handler; |
85 | $this->cookieManager = $cookieManager; |
86 | $this->cipher = BlockCipher::factory('openssl'); |
87 | } |
88 | |
89 | /** |
90 | * Closes a session. |
91 | * |
92 | * @return bool |
93 | */ |
94 | public function close(): bool |
95 | { |
96 | return $this->__call(__FUNCTION__, []); |
97 | } |
98 | |
99 | /** |
100 | * Destroys a session. |
101 | * |
102 | * @param string $id Session ID |
103 | * |
104 | * @return bool |
105 | */ |
106 | public function destroy(string $id): bool |
107 | { |
108 | return $this->__call(__FUNCTION__, func_get_args()); |
109 | } |
110 | |
111 | /** |
112 | * Performs garbage collection. |
113 | * |
114 | * @param int $max_lifetime Maximum session life time |
115 | * |
116 | * @return int|false |
117 | */ |
118 | public function gc(int $max_lifetime): int|false |
119 | { |
120 | return $this->__call(__FUNCTION__, func_get_args()); |
121 | } |
122 | |
123 | /** |
124 | * Opens a session. |
125 | * |
126 | * @param string $save_path Session save path |
127 | * @param string $name Session name |
128 | * |
129 | * @return bool |
130 | */ |
131 | public function open($save_path, $name): bool |
132 | { |
133 | $cookieName = "{$name}_KEY"; |
134 | $cipherKey = ($cookieValue = $this->cookieManager->get($cookieName)) |
135 | ?? base64_encode(Rand::getBytes(64)); |
136 | |
137 | if (!$cookieValue) { |
138 | $lifetime = session_get_cookie_params()['lifetime']; |
139 | $expire = $lifetime ? $lifetime + time() : 0; |
140 | $this->cookieManager->set($cookieName, $cipherKey, $expire); |
141 | } |
142 | |
143 | $this->cipher->setKey(base64_decode($cipherKey)); |
144 | return $this->handler->open($save_path, $name); |
145 | } |
146 | |
147 | /** |
148 | * Read a sessions data. |
149 | * |
150 | * @param string $session_id Session id |
151 | * |
152 | * @return string|false |
153 | */ |
154 | public function read($session_id): string|false |
155 | { |
156 | $data = $this->handler->read($session_id); |
157 | return $data ? ($this->cipher->decrypt($data) ?: '') : $data; |
158 | } |
159 | |
160 | /** |
161 | * Writes session data. |
162 | * |
163 | * @param string $session_id Session id |
164 | * @param string $session_data Session data |
165 | * |
166 | * @return bool |
167 | */ |
168 | public function write($session_id, $session_data): bool |
169 | { |
170 | $data = $this->cipher->encrypt($session_data); |
171 | return $this->handler->write($session_id, $data); |
172 | } |
173 | |
174 | /** |
175 | * Enable session writing (default) |
176 | * |
177 | * @return void |
178 | */ |
179 | public function enableWrites() |
180 | { |
181 | $this->__call(__FUNCTION__, []); |
182 | } |
183 | |
184 | /** |
185 | * Disable session writing, i.e. make it read-only |
186 | * |
187 | * @return void |
188 | */ |
189 | public function disableWrites() |
190 | { |
191 | $this->__call(__FUNCTION__, []); |
192 | } |
193 | |
194 | /** |
195 | * Get the plugin manager. Throw an exception if it is missing. |
196 | * |
197 | * @throws \Exception |
198 | * @return PluginManager |
199 | */ |
200 | public function getDbTableManager() |
201 | { |
202 | return $this->__call(__FUNCTION__, []); |
203 | } |
204 | |
205 | /** |
206 | * Set the plugin manager. |
207 | * |
208 | * @param PluginManager $manager Plugin manager |
209 | * |
210 | * @return void |
211 | */ |
212 | public function setDbTableManager(PluginManager $manager) |
213 | { |
214 | $this->__call(__FUNCTION__, func_get_args()); |
215 | } |
216 | |
217 | /** |
218 | * Pass calls to non-existing methods to the wrapped Handler |
219 | * |
220 | * @param string $name Name of the method being called |
221 | * @param array $arguments Passed Arguments |
222 | * |
223 | * @return mixed |
224 | */ |
225 | public function __call($name, $arguments) |
226 | { |
227 | return $this->handler->{$name}(...$arguments); |
228 | } |
229 | } |