ILIAS  release_7 Revision v7.30-3-g800a261c036
class.ilWACSignedPath.php
Go to the documentation of this file.
1<?php
18// declare(strict_types=1);
24
25require_once('./Services/WebAccessChecker/class.ilWACException.php');
26require_once('class.ilWACToken.php');
27require_once('./Services/WebAccessChecker/classes/class.ilWebAccessChecker.php');
28require_once './Services/WebAccessChecker/interfaces/PathType.php';
29require_once './Services/WebAccessChecker/classes/HttpServiceAware.php';
30
38{
40 const WAC_TOKEN_ID = 'il_wac_token';
41 const WAC_TIMESTAMP_ID = 'il_wac_ts';
42 const WAC_TTL_ID = 'il_wac_ttl';
43 const TS_SUFFIX = 'ts';
44 const TTL_SUFFIX = 'ttl';
45 const MAX_LIFETIME = 600;
49 protected $path_object = null;
53 protected $token_instance = null;
57 protected $type = PathType::FILE;
61 protected static $token_max_lifetime_in_seconds = 3;
65 protected static $cookie_max_lifetime_in_seconds = 300;
69 protected $checked = false;
73 private $httpService;
78
79
87 public function __construct(ilWACPath $ilWACPath, GlobalHttpState $httpState, CookieFactory $cookieFactory)
88 {
89 $this->setPathObject($ilWACPath);
90 $this->httpService = $httpState;
91 $this->cookieFactory = $cookieFactory;
92 }
93
94
99 public function getSignedPath()
100 {
101 if ($this->getType() !== PathType::FILE) {
103 }
104 if (!$this->getPathObject()->getOriginalRequest()) {
105 return '';
106 }
107 if (!$this->getPathObject()->fileExists()) {
108 // return $this->getPathObject()->getOriginalRequest();
109 }
110
111 if (strpos($this->getPathObject()->getPath(), '?')) {
112 $path = $this->getPathObject()->getPath() . '&' . self::WAC_TOKEN_ID . '='
113 . $this->getTokenInstance()->getToken();
114 } else {
115 $path = $this->getPathObject()->getPath() . '?' . self::WAC_TOKEN_ID . '='
116 . $this->getTokenInstance()->getToken();
117 }
118
119 $path = $path . '&' . self::WAC_TTL_ID . '=' . $this->getTokenInstance()->getTTL();
120 $path = $path . '&' . self::WAC_TIMESTAMP_ID . '='
121 . $this->getTokenInstance()->getTimestamp();
122
123 return $path;
124 }
125
126
130 public function isFolderSigned()
131 {
132 $jar = $this->httpService->cookieJar();
133 $cookies = $jar->getAll();
134
135 $this->setType(PathType::FOLDER);
136 $plain_token = $this->buildTokenInstance();
137 $name = $plain_token->getHashedId();
138
139 // Token
140 $default_token = '';
141 $token_cookie_value = $this->httpService->request()->getCookieParams()[$name] ?? $default_token;
142 // Timestamp
143 $default_timestamp = 0;
144 $timestamp_cookie_value = $this->httpService->request()->getCookieParams()[$name . self::TS_SUFFIX] ?? $default_timestamp;
145 $timestamp_cookie_value = intval($timestamp_cookie_value);
146 // TTL
147 $default_ttl = 0;
148 $ttl_cookie_value = $this->httpService->request()->getCookieParams()[$name . self::TTL_SUFFIX] ?? $default_ttl;
149 $ttl_cookie_value = intval($ttl_cookie_value);
150
151 $this->getPathObject()->setToken($token_cookie_value);
152 $this->getPathObject()->setTimestamp($timestamp_cookie_value);
153 $this->getPathObject()->setTTL($ttl_cookie_value);
155
156 return $this->getPathObject()->hasToken();
157 }
158
159
164 public function isFolderTokenValid()
165 {
166 if (!$this->isFolderSigned()) {
167 return false;
168 }
169
170 return $this->checkToken();
171 }
172
173
177 protected function saveFolderToken()
178 {
179 $ttl = $this->getPathObject()->getTTL();
180 $cookie_lifetime = $ttl !== 0 ? $ttl : self::getCookieMaxLifetimeInSeconds();
181 $id = $this->getTokenInstance()->getHashedId();
182 $expire = time() + $cookie_lifetime + 3600;
183 $secure = true;
184 $domain = null;
185 $http_only = true;
186 $path = '/';
187
188 $tokenCookie = $this->cookieFactory->create($id, $this->getTokenInstance()->getToken())
189 ->withExpires($expire)
190 ->withPath($path)
191 ->withSecure($secure)
192 ->withDomain($domain)
193 ->withHttpOnly($http_only);
194
195 $timestampCookie = $this->cookieFactory->create($id . self::TS_SUFFIX, time())
196 ->withExpires($expire)
197 ->withPath($path)
198 ->withDomain($domain)
199 ->withSecure($secure)
200 ->withHttpOnly($http_only);
201
202 $ttlCookie = $this->cookieFactory->create($id . self::TTL_SUFFIX, $cookie_lifetime)
203 ->withExpires($expire)
204 ->withPath($path)
205 ->withDomain($domain)
206 ->withSecure($secure)
207 ->withHttpOnly($http_only);
208
209 $jar = $this->httpService->cookieJar()->with($tokenCookie)
210 ->with($timestampCookie)
211 ->with($ttlCookie);
212
213 // FIX: currently the cookies are never stored, we must use setcookie
214 foreach ($jar->getAll() as $cookie) {
215 setcookie(
216 $cookie->getName(),
217 $cookie->getValue(),
218 $cookie->getExpires(),
219 $cookie->getPath(),
220 $cookie->getDomain(),
221 $cookie->getSecure(),
222 $cookie->getHttpOnly()
223 );
224 }
225 }
226
227
231 public function revalidatingFolderToken()
232 {
233 if ($this->getType() !== PathType::FOLDER) {
234 return false;
235 }
236 $this->buildAndSetTokenInstance(time(), $this->getPathObject()->getTTL());
237 $this->getPathObject()->setTTL($this->getTokenInstance()->getTTL());
238 $this->getPathObject()->setTimestamp($this->getTokenInstance()->getTimestamp());
239 $this->getPathObject()->setToken($this->getTokenInstance()->getToken());
240
241 $this->saveFolderToken();
242
243 return true;
244 }
245
246
250 public function isSignedPath()
251 {
252 return ($this->getPathObject()->hasToken() && $this->getPathObject()->hasTimestamp()
253 && $this->getPathObject()->hasTTL());
254 }
255
256
261 public function isSignedPathValid()
262 {
263 $this->buildAndSetTokenInstance($this->getPathObject()->getTimestamp(), $this->getPathObject()->getTTL());
264
265 return $this->checkToken();
266 }
267
268
276 public static function signFile($path_to_file)
277 {
278 if (!$path_to_file) {
279 return '';
280 }
281 $ilWACPath = new ilWACPath($path_to_file, false);
282 if (!$ilWACPath->getClient()) {
283 return $path_to_file;
284 }
285 $obj = new self($ilWACPath, self::http(), new CookieFactoryImpl());
286 $obj->setType(PathType::FILE);
287 $obj->buildAndSetTokenInstance(time(), self::getTokenMaxLifetimeInSeconds());
288
289 return $obj->getSignedPath();
290 }
291
292
297 public static function signFolderOfStartFile($start_file_path)
298 {
299 $obj = new self(new ilWACPath($start_file_path, false), self::http(), new CookieFactoryImpl());
300 $obj->setType(PathType::FOLDER);
301 $obj->buildAndSetTokenInstance(time(), self::getCookieMaxLifetimeInSeconds());
302 $obj->saveFolderToken();
303 }
304
305
309 public function getTokenInstance()
310 {
312 }
313
314
320 {
321 $this->token_instance = $token_instance;
322 }
323
324
328 public function getType()
329 {
330 return (int) $this->type;
331 }
332
333
338 public function setType($type)
339 {
340 assert(is_int($type));
341 $this->type = $type;
342 }
343
344
348 public function getPathObject()
349 {
350 return $this->path_object;
351 }
352
353
359 {
360 $this->path_object = $path_object;
361 }
362
363
368 protected function checkToken()
369 {
370 $request_token_string = $this->getPathObject()->getToken();
371 $request_ttl = $this->getPathObject()->getTTL();
372 $request_timestamp = $this->getPathObject()->getTimestamp();
373 $current_timestamp = time();
374
375 $timestamp_valid = ($current_timestamp < ($request_timestamp + $request_ttl));
376
377 if (!$timestamp_valid) {
378 $this->setChecked(true);
379
380 return false;
381 }
382
383 $simulated_token = $this->buildTokenInstance($request_timestamp, $request_ttl);
384 $simulated_token_string = $simulated_token->getToken();
385 $token_valid = ($simulated_token_string == $request_token_string);
386
387 if (!$token_valid) {
388 $this->setChecked(true);
389
390 return false;
391 }
392
393 return true;
394 }
395
396
404 protected function buildTokenInstance($timestamp = 0, $ttl = 0)
405 {
406 assert(is_int($timestamp));
407 assert(is_int($ttl));
408 if (!$this->getType()) {
410 }
411
412 switch ($this->getType()) {
413 case PathType::FOLDER:
414 $path = $this->getPathObject()->getSecurePath();
415 break;
416 default:
417 $path = $this->getPathObject()->getPathWithoutQuery();
418 break;
419 }
420
421 $client = $this->getPathObject()->getClient();
422 $timestamp = $timestamp !== 0 ? $timestamp : $this->getPathObject()->getTimestamp();
423 $ttl = $ttl !== 0 ? $ttl : $this->getPathObject()->getTTL();
424
425 return new ilWACToken($path, $client, $timestamp, $ttl);
426 }
427
428
436 public function buildAndSetTokenInstance($timestamp = 0, $ttl = 0)
437 {
438 assert(is_int($timestamp));
439 assert(is_int($ttl));
440
441 $this->setTokenInstance($this->buildTokenInstance($timestamp, $ttl));
442 }
443
444
448 public static function getTokenMaxLifetimeInSeconds()
449 {
451 }
452
453
461 {
462 assert(is_int($token_max_lifetime_in_seconds));
463 if ($token_max_lifetime_in_seconds > self::MAX_LIFETIME) {
465 }
466 self::$token_max_lifetime_in_seconds = $token_max_lifetime_in_seconds;
467 }
468
469
473 public static function getCookieMaxLifetimeInSeconds()
474 {
476 }
477
478
487 {
488 assert(is_int($cookie_max_lifetime_in_seconds));
489 if ($cookie_max_lifetime_in_seconds > self::MAX_LIFETIME) {
491 }
492 self::$cookie_max_lifetime_in_seconds = $cookie_max_lifetime_in_seconds;
493 }
494
495
499 protected function getRelevantLifeTime()
500 {
501 $request_ttl = $this->getPathObject()->getTTL();
502 if ($request_ttl > 0) {
503 return $request_ttl;
504 }
505 switch ($this->getType()) {
506 case PathType::FOLDER:
508 break;
509 case PathType::FILE:
511 break;
512 default:
513 $life_time = 0;
514 break;
515 }
516
517 return $life_time;
518 }
519
520
524 public function isChecked()
525 {
526 return (bool) $this->checked;
527 }
528
529
534 public function setChecked($checked)
535 {
536 assert(is_bool($checked));
537 $this->checked = $checked;
538 }
539}
foreach($mandatory_scripts as $file) $timestamp
Definition: buildRTE.php:81
An exception for terminatinating execution or to throw for unit testing.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
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
Interface GlobalHttpState.
Interface PathType.
Definition: PathType.php:14
if($format !==null) $name
Definition: metadata.php:230
trait HttpServiceAware
Trait HttpServiceAware.
static http()
Fetches the global http state from ILIAS.
trait HttpServiceAware
Trait HttpServiceAware.