ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
class.ilWACSignedPath.php
Go to the documentation of this file.
1<?php
2// declare(strict_types=1);
3
9
10require_once('./Services/WebAccessChecker/class.ilWACException.php');
11require_once('class.ilWACToken.php');
12require_once('./Services/WebAccessChecker/classes/class.ilWebAccessChecker.php');
13require_once './Services/WebAccessChecker/interfaces/PathType.php';
14require_once './Services/WebAccessChecker/classes/HttpServiceAware.php';
15
23{
25 const WAC_TOKEN_ID = 'il_wac_token';
26 const WAC_TIMESTAMP_ID = 'il_wac_ts';
27 const WAC_TTL_ID = 'il_wac_ttl';
28 const TS_SUFFIX = 'ts';
29 const TTL_SUFFIX = 'ttl';
30 const MAX_LIFETIME = 600;
34 protected $path_object = null;
38 protected $token_instance = null;
42 protected $type = PathType::FILE;
46 protected static $token_max_lifetime_in_seconds = 3;
50 protected static $cookie_max_lifetime_in_seconds = 300;
54 protected $checked = false;
58 private $httpService;
63
64
72 public function __construct(ilWACPath $ilWACPath, GlobalHttpState $httpState, CookieFactory $cookieFactory)
73 {
74 $this->setPathObject($ilWACPath);
75 $this->httpService = $httpState;
76 $this->cookieFactory = $cookieFactory;
77 }
78
79
84 public function getSignedPath()
85 {
86 if ($this->getType() !== PathType::FILE) {
88 }
89 if (!$this->getPathObject()->getOriginalRequest()) {
90 return '';
91 }
92 if (!$this->getPathObject()->fileExists()) {
93 // return $this->getPathObject()->getOriginalRequest();
94 }
95
96 if (strpos($this->getPathObject()->getPath(), '?')) {
97 $path = $this->getPathObject()->getPath() . '&' . self::WAC_TOKEN_ID . '='
98 . $this->getTokenInstance()->getToken();
99 } else {
100 $path = $this->getPathObject()->getPath() . '?' . self::WAC_TOKEN_ID . '='
101 . $this->getTokenInstance()->getToken();
102 }
103
104 $path = $path . '&' . self::WAC_TTL_ID . '=' . $this->getTokenInstance()->getTTL();
105 $path = $path . '&' . self::WAC_TIMESTAMP_ID . '='
106 . $this->getTokenInstance()->getTimestamp();
107
108 return $path;
109 }
110
111
115 public function isFolderSigned()
116 {
117 $jar = $this->httpService->cookieJar();
118 $cookies = $jar->getAll();
119
120 $this->setType(PathType::FOLDER);
121 $timestamp = time();
122 $plain_token = $this->buildTokenInstance($timestamp, self::getCookieMaxLifetimeInSeconds());
123 $name = $plain_token->getHashedId();
124
125 // Token
126 $default_token = '';
127 $token_cookie_value = $this->httpService->request()->getCookieParams()[$name] ?? $default_token;
128 // Timestamp
129 $default_timestamp = 0;
130 $timestamp_cookie_value = $this->httpService->request()->getCookieParams()[$name . self::TS_SUFFIX] ?? $default_timestamp;
131 $timestamp_cookie_value = intval($timestamp_cookie_value);
132 // TTL
133 $default_ttl = 0;
134 $ttl_cookie_value = $this->httpService->request()->getCookieParams()[$name . self::TTL_SUFFIX] ?? $default_ttl;
135 $ttl_cookie_value = intval($ttl_cookie_value);
136
137 $this->getPathObject()->setToken($token_cookie_value);
138 $this->getPathObject()->setTimestamp($timestamp_cookie_value);
139 $this->getPathObject()->setTTL($ttl_cookie_value);
140 $this->buildAndSetTokenInstance($timestamp, self::getCookieMaxLifetimeInSeconds());
141
142 return $this->getPathObject()->hasToken();
143 }
144
145
150 public function isFolderTokenValid()
151 {
152 if (!$this->isFolderSigned()) {
153 return false;
154 }
155
156 return $this->checkToken();
157 }
158
159
163 protected function saveFolderToken()
164 {
165 $cookie_lifetime = self::getCookieMaxLifetimeInSeconds();
166 $id = $this->getTokenInstance()->getHashedId();
167 $expire = time() + $cookie_lifetime + 3600;
168 $secure = true;
169 $domain = null;
170 $http_only = true;
171 $path = '/';
172
173 $tokenCookie = $this->cookieFactory->create($id, $this->getTokenInstance()->getToken())
174 ->withExpires($expire)
175 ->withPath($path)
176 ->withSecure($secure)
177 ->withDomain($domain)
178 ->withHttpOnly($http_only);
179
180 $timestampCookie = $this->cookieFactory->create($id . self::TS_SUFFIX, time())
181 ->withExpires($expire)
182 ->withPath($path)
183 ->withDomain($domain)
184 ->withSecure($secure)
185 ->withHttpOnly($http_only);
186
187 $ttlCookie = $this->cookieFactory->create($id . self::TTL_SUFFIX, $cookie_lifetime)
188 ->withExpires($expire)
189 ->withPath($path)
190 ->withDomain($domain)
191 ->withSecure($secure)
192 ->withHttpOnly($http_only);
193
194 $response = $this->httpService->cookieJar()->with($tokenCookie)
195 ->with($timestampCookie)
196 ->with($ttlCookie)
197 ->renderIntoResponseHeader($this->httpService->response());
198
199 // FIX: currently the cookies are never stored
200 foreach ($this->httpService->cookieJar()->getAll() as $cookie) {
201 setcookie($cookie->getName(), $cookie->getValue(), $cookie->getExpires(), $cookie->getPath(), $cookie->getDomain(), $cookie->getSecure(), $cookie->getHttpOnly());
202 }
203
204 $this->httpService->saveResponse($response);
205 }
206
207
211 public function revalidatingFolderToken()
212 {
213 if ($this->getType() !== PathType::FOLDER) {
214 return false;
215 }
216 $this->buildAndSetTokenInstance(time(), self::getCookieMaxLifetimeInSeconds());
217 $this->saveFolderToken();
218
219 return true;
220 }
221
222
226 public function isSignedPath()
227 {
228 return ($this->getPathObject()->hasToken() && $this->getPathObject()->hasTimestamp()
229 && $this->getPathObject()->hasTTL());
230 }
231
232
237 public function isSignedPathValid()
238 {
239 $this->buildAndSetTokenInstance($this->getPathObject()->getTimestamp(), $this->getPathObject()->getTTL());
240
241 return $this->checkToken();
242 }
243
244
252 public static function signFile($path_to_file)
253 {
254 if (!$path_to_file) {
255 return '';
256 }
257 $ilWACPath = new ilWACPath($path_to_file);
258 if (!$ilWACPath->getClient()) {
259 return $path_to_file;
260 }
261 $obj = new self($ilWACPath, self::http(), new CookieFactoryImpl());
262 $obj->setType(PathType::FILE);
263 $obj->buildAndSetTokenInstance(time(), self::getTokenMaxLifetimeInSeconds());
264
265 return $obj->getSignedPath();
266 }
267
268
273 public static function signFolderOfStartFile($start_file_path)
274 {
275 $obj = new self(new ilWACPath($start_file_path), self::http(), new CookieFactoryImpl());
276 $obj->setType(PathType::FOLDER);
277 $obj->buildAndSetTokenInstance(time(), self::getCookieMaxLifetimeInSeconds());
278 $obj->saveFolderToken();
279 }
280
281
285 public function getTokenInstance()
286 {
288 }
289
290
296 {
297 $this->token_instance = $token_instance;
298 }
299
300
304 public function getType()
305 {
306 return (int) $this->type;
307 }
308
309
314 public function setType($type)
315 {
316 assert(is_int($type));
317 $this->type = $type;
318 }
319
320
324 public function getPathObject()
325 {
326 return $this->path_object;
327 }
328
329
335 {
336 $this->path_object = $path_object;
337 }
338
339
344 protected function checkToken()
345 {
346 $request_token = $this->getPathObject()->getToken();
347 $request_ttl = $this->getPathObject()->getTTL();
348 $request_timestamp = $this->getPathObject()->getTimestamp();
349 $current_timestamp = time();
350
351 $timestamp_valid = ($current_timestamp < ($request_timestamp + $request_ttl));
352
353 if (!$timestamp_valid) {
354 $this->setChecked(true);
355
356 return false;
357 }
358
359 $simulatedTokenInstance = $this->buildTokenInstance($request_timestamp, $request_ttl);
360 $token_valid = ($simulatedTokenInstance->getToken() == $request_token);
361
362 if (!$token_valid) {
363 $this->setChecked(true);
364
365 return false;
366 }
367
368 return true;
369 }
370
371
379 protected function buildTokenInstance($timestamp = 0, $ttl = 0)
380 {
381 assert(is_int($timestamp));
382 assert(is_int($ttl));
383 if (!$this->getType()) {
385 }
386
387 switch ($this->getType()) {
388 case PathType::FOLDER:
389 $path = $this->getPathObject()->getModulePath();
390 break;
391 case PathType::FILE:
392 $path = $this->getPathObject()->getPathWithoutQuery();
393 break;
394 default:
395 $path = $this->getPathObject()->getPathWithoutQuery();
396 break;
397 }
398
399 $client = $this->getPathObject()->getClient();
400 $timestamp = $timestamp ? $timestamp : $this->getPathObject()->getTimestamp();
401 $ttl = $ttl ? $ttl : $this->getPathObject()->getTTL();
402
403 return new ilWACToken($path, $client, $timestamp, $ttl);
404 }
405
406
414 public function buildAndSetTokenInstance($timestamp = 0, $ttl = 0)
415 {
416 assert(is_int($timestamp));
417 assert(is_int($ttl));
418
419 $this->setTokenInstance($this->buildTokenInstance($timestamp, $ttl));
420 }
421
422
426 public static function getTokenMaxLifetimeInSeconds()
427 {
429 }
430
431
439 {
440 assert(is_int($token_max_lifetime_in_seconds));
441 if ($token_max_lifetime_in_seconds > self::MAX_LIFETIME) {
443 }
444 self::$token_max_lifetime_in_seconds = $token_max_lifetime_in_seconds;
445 }
446
447
451 public static function getCookieMaxLifetimeInSeconds()
452 {
454 }
455
456
465 {
466 assert(is_int($cookie_max_lifetime_in_seconds));
467 if ($cookie_max_lifetime_in_seconds > self::MAX_LIFETIME) {
469 }
470 self::$cookie_max_lifetime_in_seconds = $cookie_max_lifetime_in_seconds;
471 }
472
473
477 protected function getRelevantLifeTime()
478 {
479 $request_ttl = $this->getPathObject()->getTTL();
480 if ($request_ttl > 0) {
481 return $request_ttl;
482 }
483 switch ($this->getType()) {
484 case PathType::FOLDER:
486 break;
487 case PathType::FILE:
489 break;
490 default:
491 $life_time = 0;
492 break;
493 }
494
495 return $life_time;
496 }
497
498
502 public function isChecked()
503 {
504 return (bool) $this->checked;
505 }
506
507
512 public function setChecked($checked)
513 {
514 assert(is_bool($checked));
515 $this->checked = $checked;
516 }
517}
$path
Definition: aliased.php:25
foreach($mandatory_scripts as $file) $timestamp
Definition: buildRTE.php:81
if(!array_key_exists('domain', $_REQUEST)) $domain
Definition: resume.php:8
An exception for terminatinating execution or to throw for unit testing.
Class ilWACException.
Class ilWACPath.
Class ilWACSignedPath.
static signFile($path_to_file)
__construct(ilWACPath $ilWACPath, GlobalHttpState $httpState, CookieFactory $cookieFactory)
ilWACSignedPath constructor.
setTokenInstance(ilWACToken $token_instance)
static getCookieMaxLifetimeInSeconds()
static setCookieMaxLifetimeInSeconds($cookie_max_lifetime_in_seconds)
buildAndSetTokenInstance($timestamp=0, $ttl=0)
setPathObject(ilWACPath $path_object)
static setTokenMaxLifetimeInSeconds($token_max_lifetime_in_seconds)
static $cookie_max_lifetime_in_seconds
static signFolderOfStartFile($start_file_path)
buildTokenInstance($timestamp=0, $ttl=0)
static getTokenMaxLifetimeInSeconds()
Class ilWACToken.
if($_SERVER['argc']< 4) $client
Definition: cron.php:12
if(!array_key_exists('StateId', $_REQUEST)) $id
Interface GlobalHttpState.
Interface PathType.
Definition: PathType.php:14
$expire
Definition: saml2-acs.php:140
trait HttpServiceAware
Trait HttpServiceAware.
static http()
Fetches the global http state from ILIAS.
trait HttpServiceAware
Trait HttpServiceAware.
$response