ILIAS  release_6 Revision v6.24-5-g0c8bfefb3b8
All Data Structures Namespaces Files Functions Variables Modules Pages
class.ilWACSignedPath.php
Go to the documentation of this file.
1 <?php
2 // declare(strict_types=1);
3 
9 
10 require_once('./Services/WebAccessChecker/class.ilWACException.php');
11 require_once('class.ilWACToken.php');
12 require_once('./Services/WebAccessChecker/classes/class.ilWebAccessChecker.php');
13 require_once './Services/WebAccessChecker/interfaces/PathType.php';
14 require_once './Services/WebAccessChecker/classes/HttpServiceAware.php';
15 
23 {
24  use HttpServiceAware;
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 = 20;
50  protected static $cookie_max_lifetime_in_seconds = 300;
54  protected $checked = false;
58  private $httpService;
62  private $cookieFactory;
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  $plain_token = $this->buildTokenInstance();
122  $name = $plain_token->getHashedId();
123 
124  // Token
125  $default_token = '';
126  $token_cookie_value = $this->httpService->request()->getCookieParams()[$name] ?? $default_token;
127  // Timestamp
128  $default_timestamp = 0;
129  $timestamp_cookie_value = $this->httpService->request()->getCookieParams()[$name . self::TS_SUFFIX] ?? $default_timestamp;
130  $timestamp_cookie_value = intval($timestamp_cookie_value);
131  // TTL
132  $default_ttl = 0;
133  $ttl_cookie_value = $this->httpService->request()->getCookieParams()[$name . self::TTL_SUFFIX] ?? $default_ttl;
134  $ttl_cookie_value = intval($ttl_cookie_value);
135 
136  $this->getPathObject()->setToken($token_cookie_value);
137  $this->getPathObject()->setTimestamp($timestamp_cookie_value);
138  $this->getPathObject()->setTTL($ttl_cookie_value);
139  $this->buildAndSetTokenInstance();
140 
141  return $this->getPathObject()->hasToken();
142  }
143 
144 
149  public function isFolderTokenValid()
150  {
151  if (!$this->isFolderSigned()) {
152  return false;
153  }
154 
155  return $this->checkToken();
156  }
157 
158 
162  protected function saveFolderToken()
163  {
164  $ttl = $this->getPathObject()->getTTL();
165  $cookie_lifetime = $ttl !== 0 ? $ttl : 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  $jar = $this->httpService->cookieJar()->with($tokenCookie)
195  ->with($timestampCookie)
196  ->with($ttlCookie);
197 
198  // FIX: currently the cookies are never stored, we must use setcookie
199  foreach ($jar->getAll() as $cookie) {
200  setcookie($cookie->getName(), $cookie->getValue(), $cookie->getExpires(), $cookie->getPath(),
201  $cookie->getDomain(), $cookie->getSecure(), $cookie->getHttpOnly());
202  }
203  }
204 
205 
209  public function revalidatingFolderToken()
210  {
211  if ($this->getType() !== PathType::FOLDER) {
212  return false;
213  }
214  $this->buildAndSetTokenInstance(time(), $this->getPathObject()->getTTL());
215  $this->getPathObject()->setTTL($this->getTokenInstance()->getTTL());
216  $this->getPathObject()->setTimestamp($this->getTokenInstance()->getTimestamp());
217  $this->getPathObject()->setToken($this->getTokenInstance()->getToken());
218 
219  $this->saveFolderToken();
220 
221  return true;
222  }
223 
224 
228  public function isSignedPath()
229  {
230  return ($this->getPathObject()->hasToken() && $this->getPathObject()->hasTimestamp()
231  && $this->getPathObject()->hasTTL());
232  }
233 
234 
239  public function isSignedPathValid()
240  {
241  $this->buildAndSetTokenInstance($this->getPathObject()->getTimestamp(), $this->getPathObject()->getTTL());
242 
243  return $this->checkToken();
244  }
245 
246 
254  public static function signFile($path_to_file)
255  {
256  if (!$path_to_file) {
257  return '';
258  }
259  $ilWACPath = new ilWACPath($path_to_file);
260  if (!$ilWACPath->getClient()) {
261  return $path_to_file;
262  }
263  $obj = new self($ilWACPath, self::http(), new CookieFactoryImpl());
264  $obj->setType(PathType::FILE);
265  $obj->buildAndSetTokenInstance(time(), self::getTokenMaxLifetimeInSeconds());
266 
267  return $obj->getSignedPath();
268  }
269 
270 
275  public static function signFolderOfStartFile($start_file_path)
276  {
277  $obj = new self(new ilWACPath($start_file_path), self::http(), new CookieFactoryImpl());
278  $obj->setType(PathType::FOLDER);
279  $obj->buildAndSetTokenInstance(time(), self::getCookieMaxLifetimeInSeconds());
280  $obj->saveFolderToken();
281  }
282 
283 
287  public function getTokenInstance()
288  {
289  return $this->token_instance;
290  }
291 
292 
298  {
299  $this->token_instance = $token_instance;
300  }
301 
302 
306  public function getType()
307  {
308  return (int) $this->type;
309  }
310 
311 
316  public function setType($type)
317  {
318  assert(is_int($type));
319  $this->type = $type;
320  }
321 
322 
326  public function getPathObject()
327  {
328  return $this->path_object;
329  }
330 
331 
337  {
338  $this->path_object = $path_object;
339  }
340 
341 
346  protected function checkToken()
347  {
348  $request_token_string = $this->getPathObject()->getToken();
349  $request_ttl = $this->getPathObject()->getTTL();
350  $request_timestamp = $this->getPathObject()->getTimestamp();
351  $current_timestamp = time();
352 
353  $timestamp_valid = ($current_timestamp < ($request_timestamp + $request_ttl));
354 
355  if (!$timestamp_valid) {
356  $this->setChecked(true);
357 
358  return false;
359  }
360 
361  $simulated_token = $this->buildTokenInstance($request_timestamp, $request_ttl);
362  $simulated_token_string = $simulated_token->getToken();
363  $token_valid = ($simulated_token_string == $request_token_string);
364 
365  if (!$token_valid) {
366  $this->setChecked(true);
367 
368  return false;
369  }
370 
371  return true;
372  }
373 
374 
382  protected function buildTokenInstance($timestamp = 0, $ttl = 0)
383  {
384  assert(is_int($timestamp));
385  assert(is_int($ttl));
386  if (!$this->getType()) {
388  }
389 
390  switch ($this->getType()) {
391  case PathType::FOLDER:
392  $path = $this->getPathObject()->getSecurePath();
393  break;
394  default:
395  $path = $this->getPathObject()->getPathWithoutQuery();
396  break;
397  }
398 
399  $client = $this->getPathObject()->getClient();
400  $timestamp = $timestamp !== 0 ? $timestamp : $this->getPathObject()->getTimestamp();
401  $ttl = $ttl !== 0 ? $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  {
428  return self::$token_max_lifetime_in_seconds;
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  {
453  return self::$cookie_max_lifetime_in_seconds;
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:
485  $life_time = self::getCookieMaxLifetimeInSeconds();
486  break;
487  case PathType::FILE:
488  $life_time = self::getTokenMaxLifetimeInSeconds();
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 }
Interface GlobalHttpState.
buildTokenInstance($timestamp=0, $ttl=0)
Class ilWACException.
static getCookieMaxLifetimeInSeconds()
setTokenInstance(ilWACToken $token_instance)
if($_SERVER['argc']< 4) $client
Definition: cron.php:12
__construct(ilWACPath $ilWACPath, GlobalHttpState $httpState, CookieFactory $cookieFactory)
ilWACSignedPath constructor.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
trait HttpServiceAware
Trait HttpServiceAware.
static signFolderOfStartFile($start_file_path)
if($format !==null) $name
Definition: metadata.php:230
static http()
Fetches the global http state from ILIAS.
setPathObject(ilWACPath $path_object)
static setCookieMaxLifetimeInSeconds($cookie_max_lifetime_in_seconds)
buildAndSetTokenInstance($timestamp=0, $ttl=0)
Class ilWACSignedPath.
static signFile($path_to_file)
Class ilWACToken.
foreach($mandatory_scripts as $file) $timestamp
Definition: buildRTE.php:81
trait HttpServiceAware
Trait HttpServiceAware.
static setTokenMaxLifetimeInSeconds($token_max_lifetime_in_seconds)
static getTokenMaxLifetimeInSeconds()
static $cookie_max_lifetime_in_seconds